[OpenLayers-Commits] r10920 - in sandbox/ahocevar/playground: . apidoc_config build doc_config examples img lib lib/OpenLayers lib/OpenLayers/BaseTypes lib/OpenLayers/Control lib/OpenLayers/Feature lib/OpenLayers/Filter lib/OpenLayers/Format lib/OpenLayers/Format/ArcXML lib/OpenLayers/Format/CSWGetDomain lib/OpenLayers/Format/CSWGetRecords lib/OpenLayers/Format/Filter lib/OpenLayers/Format/GML lib/OpenLayers/Format/OWSCommon lib/OpenLayers/Format/OWSContext lib/OpenLayers/Format/SLD lib/OpenLayers/Format/SOSCapabilities lib/OpenLayers/Format/WFSCapabilities lib/OpenLayers/Format/WFST lib/OpenLayers/Format/WMC lib/OpenLayers/Format/WMSCapabilities lib/OpenLayers/Format/WMSDescribeLayer lib/OpenLayers/Format/WMTSCapabilities lib/OpenLayers/Geometry lib/OpenLayers/Handler lib/OpenLayers/Lang lib/OpenLayers/Layer lib/OpenLayers/Layer/Google lib/OpenLayers/Layer/MapServer lib/OpenLayers/Layer/Vector lib/OpenLayers/Layer/WMS lib/OpenLayers/Marker lib/OpenLayers/Popup lib/OpenLayers/Protocol li b/OpenLayers/Protocol/SOS lib/OpenLayers/Protocol/SQL lib/OpenLayers/Protocol/WFS lib/OpenLayers/Renderer lib/OpenLayers/Request lib/OpenLayers/Strategy lib/OpenLayers/Symbolizer lib/OpenLayers/Tile lib/OpenLayers/Tile/Image tests tests/BaseTypes tests/Control tests/Feature tests/Filter tests/Format tests/Format/CSWGetDomain tests/Format/CSWGetRecords tests/Format/Filter tests/Format/GML tests/Format/OWSContext tests/Format/SLD tests/Format/SOSCapabilities tests/Format/WFSCapabilities tests/Format/WFST tests/Format/WMC tests/Format/WMSCapabilities tests/Format/WMTSCapabilities tests/Geometry tests/Handler tests/Layer tests/Layer/Google tests/Layer/WMS tests/Marker tests/Popup tests/Protocol tests/Renderer tests/Strategy tests/Symbolizer tests/Tile tests/Tile/Image tests/data tests/manual tests/manual/memory tests/speed theme/default theme/default/img tools

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Sun Nov 28 10:49:00 EST 2010


Author: ahocevar
Date: 2010-11-28 07:48:59 -0800 (Sun, 28 Nov 2010)
New Revision: 10920

Added:
   sandbox/ahocevar/playground/examples/SLDSelect.html
   sandbox/ahocevar/playground/examples/WMSPost.html
   sandbox/ahocevar/playground/examples/all-overlays-google.html
   sandbox/ahocevar/playground/examples/all-overlays-google.js
   sandbox/ahocevar/playground/examples/bing.html
   sandbox/ahocevar/playground/examples/canvas.html
   sandbox/ahocevar/playground/examples/canvas.js
   sandbox/ahocevar/playground/examples/document-drag.html
   sandbox/ahocevar/playground/examples/donut.html
   sandbox/ahocevar/playground/examples/donut.js
   sandbox/ahocevar/playground/examples/dynamic-text-layer.html
   sandbox/ahocevar/playground/examples/example.js
   sandbox/ahocevar/playground/examples/filter-strategy.html
   sandbox/ahocevar/playground/examples/filter-strategy.js
   sandbox/ahocevar/playground/examples/getfeatureinfo-popup.html
   sandbox/ahocevar/playground/examples/google-v3-alloverlays.html
   sandbox/ahocevar/playground/examples/google-v3-alloverlays.js
   sandbox/ahocevar/playground/examples/google-v3.html
   sandbox/ahocevar/playground/examples/google-v3.js
   sandbox/ahocevar/playground/examples/graticule.html
   sandbox/ahocevar/playground/examples/kml-layer.js
   sandbox/ahocevar/playground/examples/kml-track.html
   sandbox/ahocevar/playground/examples/kml-track.js
   sandbox/ahocevar/playground/examples/kml-track.kml
   sandbox/ahocevar/playground/examples/mousewheel-interval.html
   sandbox/ahocevar/playground/examples/osm-google.html
   sandbox/ahocevar/playground/examples/osm-google.js
   sandbox/ahocevar/playground/examples/osm.html
   sandbox/ahocevar/playground/examples/single-tile.html
   sandbox/ahocevar/playground/examples/single-tile.js
   sandbox/ahocevar/playground/examples/sld-parser.html
   sandbox/ahocevar/playground/examples/sos.html
   sandbox/ahocevar/playground/examples/strategy-cluster-extended.html
   sandbox/ahocevar/playground/examples/strategy-cluster-extended.js
   sandbox/ahocevar/playground/examples/style-rules.html
   sandbox/ahocevar/playground/examples/style-rules.js
   sandbox/ahocevar/playground/examples/transform-feature.html
   sandbox/ahocevar/playground/examples/web-mercator.html
   sandbox/ahocevar/playground/examples/web-mercator.js
   sandbox/ahocevar/playground/examples/wfs-filter.html
   sandbox/ahocevar/playground/examples/wfs-filter.js
   sandbox/ahocevar/playground/examples/wfs-protocol-transactions.js
   sandbox/ahocevar/playground/examples/wfs-reprojection.js
   sandbox/ahocevar/playground/examples/wfs-states.js
   sandbox/ahocevar/playground/examples/wms-long-url.html
   sandbox/ahocevar/playground/examples/wms-long-url.js
   sandbox/ahocevar/playground/examples/wms-v13.html
   sandbox/ahocevar/playground/examples/wmts-capabilities.html
   sandbox/ahocevar/playground/examples/wmts-capabilities.js
   sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.html
   sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.js
   sandbox/ahocevar/playground/examples/wmts.html
   sandbox/ahocevar/playground/examples/wmts.js
   sandbox/ahocevar/playground/examples/xyz-offset.html
   sandbox/ahocevar/playground/examples/xyz-offset.js
   sandbox/ahocevar/playground/examples/zoomify.html
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Graticule.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/SLDSelect.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/TransformFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/WMTSGetFeatureInfo.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Atom.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Context.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetObservation.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ar.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/be-tarask.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/bg.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/br.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/el.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/fi.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/fur.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/gl.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/gsw.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/hr.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/hsb.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/hu.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ia.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/id.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/io.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/is.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ja.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/km.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ksh.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/nds.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/nn.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/oc.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ru.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/sk.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/te.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/vi.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Post.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMTS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Zoomify.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Filter.js
   sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Refresh.js
   sandbox/ahocevar/playground/lib/OpenLayers/Style2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/
   sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js
   sandbox/ahocevar/playground/tests/Control/Graticule.html
   sandbox/ahocevar/playground/tests/Control/PanPanel.html
   sandbox/ahocevar/playground/tests/Control/SLDSelect.html
   sandbox/ahocevar/playground/tests/Control/TransformFeature.html
   sandbox/ahocevar/playground/tests/Control/WMTSGetFeatureInfo.html
   sandbox/ahocevar/playground/tests/Format/Atom.html
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain.html
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain/
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords.html
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords/
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js
   sandbox/ahocevar/playground/tests/Format/OWSContext/
   sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html
   sandbox/ahocevar/playground/tests/Format/SOSCapabilities/
   sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html
   sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/tests/Format/SOSGetFeatureOfInterest.html
   sandbox/ahocevar/playground/tests/Format/SOSGetObservation.html
   sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_3_0.html
   sandbox/ahocevar/playground/tests/Format/WMTSCapabilities.html
   sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/
   sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html
   sandbox/ahocevar/playground/tests/Layer/Google/
   sandbox/ahocevar/playground/tests/Layer/Google/v3.html
   sandbox/ahocevar/playground/tests/Layer/WMS/
   sandbox/ahocevar/playground/tests/Layer/WMS/Post.html
   sandbox/ahocevar/playground/tests/Layer/WMTS.html
   sandbox/ahocevar/playground/tests/OpenLayers1.html
   sandbox/ahocevar/playground/tests/OpenLayers2.html
   sandbox/ahocevar/playground/tests/OpenLayers3.html
   sandbox/ahocevar/playground/tests/OpenLayers4.html
   sandbox/ahocevar/playground/tests/Protocol/SOS.html
   sandbox/ahocevar/playground/tests/Strategy/Filter.html
   sandbox/ahocevar/playground/tests/Strategy/Refresh.html
   sandbox/ahocevar/playground/tests/Style2.html
   sandbox/ahocevar/playground/tests/Symbolizer.html
   sandbox/ahocevar/playground/tests/Symbolizer/
   sandbox/ahocevar/playground/tests/Symbolizer/Line.html
   sandbox/ahocevar/playground/tests/Symbolizer/Point.html
   sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html
   sandbox/ahocevar/playground/tests/Symbolizer/Raster.html
   sandbox/ahocevar/playground/tests/Symbolizer/Text.html
   sandbox/ahocevar/playground/tests/Tile/Image/
   sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html
   sandbox/ahocevar/playground/tests/manual/arcims-2117.html
   sandbox/ahocevar/playground/tests/manual/geodesic.html
   sandbox/ahocevar/playground/tests/manual/google-resize.html
   sandbox/ahocevar/playground/tests/manual/memory/
   sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html
   sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html
   sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html
   sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html
   sandbox/ahocevar/playground/tests/manual/multiple-google-layers.html
   sandbox/ahocevar/playground/tests/manual/page-position.html
   sandbox/ahocevar/playground/tests/speed/wmscaps.html
   sandbox/ahocevar/playground/tests/speed/wmscaps.js
   sandbox/ahocevar/playground/tests/speed/wmscaps.xml
   sandbox/ahocevar/playground/tools/mkrelease.sh
Removed:
   sandbox/ahocevar/playground/examples/wfs.html
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js
   sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html
   sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html
   sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js
   sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html
   sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html
   sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html
   sandbox/ahocevar/playground/tests/Layer/Google/v3.html
   sandbox/ahocevar/playground/tests/Layer/WMS/Post.html
   sandbox/ahocevar/playground/tests/Symbolizer/Line.html
   sandbox/ahocevar/playground/tests/Symbolizer/Point.html
   sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html
   sandbox/ahocevar/playground/tests/Symbolizer/Raster.html
   sandbox/ahocevar/playground/tests/Symbolizer/Text.html
   sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html
   sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html
   sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html
   sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html
   sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html
Modified:
   sandbox/ahocevar/playground/
   sandbox/ahocevar/playground/apidoc_config/Menu.txt
   sandbox/ahocevar/playground/build/build.py
   sandbox/ahocevar/playground/build/full.cfg
   sandbox/ahocevar/playground/build/library.cfg
   sandbox/ahocevar/playground/build/license.txt
   sandbox/ahocevar/playground/build/lite.cfg
   sandbox/ahocevar/playground/doc_config/Menu.txt
   sandbox/ahocevar/playground/examples/GMLParser.html
   sandbox/ahocevar/playground/examples/Jugl.js
   sandbox/ahocevar/playground/examples/KMLParser.html
   sandbox/ahocevar/playground/examples/WMSDescribeLayerParser.html
   sandbox/ahocevar/playground/examples/accessible.html
   sandbox/ahocevar/playground/examples/all-overlays.html
   sandbox/ahocevar/playground/examples/animated_panning.html
   sandbox/ahocevar/playground/examples/arcgis93rest.html
   sandbox/ahocevar/playground/examples/arcims-thematic.html
   sandbox/ahocevar/playground/examples/arcims.html
   sandbox/ahocevar/playground/examples/attribution.html
   sandbox/ahocevar/playground/examples/baseLayers.html
   sandbox/ahocevar/playground/examples/behavior-fixed-http-gml.html
   sandbox/ahocevar/playground/examples/boxes-vector.html
   sandbox/ahocevar/playground/examples/boxes.html
   sandbox/ahocevar/playground/examples/browser-name.html
   sandbox/ahocevar/playground/examples/buffer.html
   sandbox/ahocevar/playground/examples/click-handler.html
   sandbox/ahocevar/playground/examples/click.html
   sandbox/ahocevar/playground/examples/controls.html
   sandbox/ahocevar/playground/examples/custom-control-point.html
   sandbox/ahocevar/playground/examples/custom-control.html
   sandbox/ahocevar/playground/examples/custom-style.html
   sandbox/ahocevar/playground/examples/debug.html
   sandbox/ahocevar/playground/examples/doubleSetCenter.html
   sandbox/ahocevar/playground/examples/drag-feature.html
   sandbox/ahocevar/playground/examples/draw-feature.html
   sandbox/ahocevar/playground/examples/editingtoolbar-outside.html
   sandbox/ahocevar/playground/examples/editingtoolbar.html
   sandbox/ahocevar/playground/examples/events.html
   sandbox/ahocevar/playground/examples/example-list.html
   sandbox/ahocevar/playground/examples/example.html
   sandbox/ahocevar/playground/examples/filter.html
   sandbox/ahocevar/playground/examples/fractional-zoom.html
   sandbox/ahocevar/playground/examples/fullScreen.html
   sandbox/ahocevar/playground/examples/geojson.html
   sandbox/ahocevar/playground/examples/georss-flickr.html
   sandbox/ahocevar/playground/examples/georss-markers.html
   sandbox/ahocevar/playground/examples/georss.html
   sandbox/ahocevar/playground/examples/getfeature-wfs.html
   sandbox/ahocevar/playground/examples/getfeatureinfo-control.html
   sandbox/ahocevar/playground/examples/getfeatureinfo.html
   sandbox/ahocevar/playground/examples/gml-layer.html
   sandbox/ahocevar/playground/examples/google-reproject.html
   sandbox/ahocevar/playground/examples/google.html
   sandbox/ahocevar/playground/examples/graphic-name.html
   sandbox/ahocevar/playground/examples/gutter.html
   sandbox/ahocevar/playground/examples/highlight-feature.html
   sandbox/ahocevar/playground/examples/hover-handler.html
   sandbox/ahocevar/playground/examples/image-layer.html
   sandbox/ahocevar/playground/examples/intersects.html
   sandbox/ahocevar/playground/examples/kamap.html
   sandbox/ahocevar/playground/examples/kml-layer.html
   sandbox/ahocevar/playground/examples/late-render.html
   sandbox/ahocevar/playground/examples/layer-opacity.html
   sandbox/ahocevar/playground/examples/layerLoadMonitoring.html
   sandbox/ahocevar/playground/examples/layerswitcher.html
   sandbox/ahocevar/playground/examples/lite.html
   sandbox/ahocevar/playground/examples/mapguide.html
   sandbox/ahocevar/playground/examples/mapserver.html
   sandbox/ahocevar/playground/examples/mapserver_untiled.html
   sandbox/ahocevar/playground/examples/marker-shadow.html
   sandbox/ahocevar/playground/examples/markerResize.html
   sandbox/ahocevar/playground/examples/marker_shadow.png
   sandbox/ahocevar/playground/examples/markers.html
   sandbox/ahocevar/playground/examples/markersTextLayer.html
   sandbox/ahocevar/playground/examples/measure.html
   sandbox/ahocevar/playground/examples/mm.html
   sandbox/ahocevar/playground/examples/modify-feature.html
   sandbox/ahocevar/playground/examples/mouse-position.html
   sandbox/ahocevar/playground/examples/multimap-mercator.html
   sandbox/ahocevar/playground/examples/multiserver.html
   sandbox/ahocevar/playground/examples/mvs.html
   sandbox/ahocevar/playground/examples/navigation-control.html
   sandbox/ahocevar/playground/examples/navigation-history.html
   sandbox/ahocevar/playground/examples/navtoolbar-alwaysZoom.html
   sandbox/ahocevar/playground/examples/navtoolbar-outsidemap.html
   sandbox/ahocevar/playground/examples/navtoolbar.html
   sandbox/ahocevar/playground/examples/ordering.html
   sandbox/ahocevar/playground/examples/osm-layer.html
   sandbox/ahocevar/playground/examples/outOfRangeMarkers.html
   sandbox/ahocevar/playground/examples/overviewmap.html
   sandbox/ahocevar/playground/examples/pan-zoom-panels.html
   sandbox/ahocevar/playground/examples/panel.html
   sandbox/ahocevar/playground/examples/point-track-markers.html
   sandbox/ahocevar/playground/examples/popupMatrix.html
   sandbox/ahocevar/playground/examples/popupMatrix.jpg
   sandbox/ahocevar/playground/examples/popups.html
   sandbox/ahocevar/playground/examples/projected-map.html
   sandbox/ahocevar/playground/examples/protocol-gears.html
   sandbox/ahocevar/playground/examples/proxy.cgi
   sandbox/ahocevar/playground/examples/regular-polygons.html
   sandbox/ahocevar/playground/examples/resize-features.html
   sandbox/ahocevar/playground/examples/restricted-extent.html
   sandbox/ahocevar/playground/examples/rotate-features.html
   sandbox/ahocevar/playground/examples/select-feature-multilayer.html
   sandbox/ahocevar/playground/examples/select-feature-openpopup.html
   sandbox/ahocevar/playground/examples/select-feature.html
   sandbox/ahocevar/playground/examples/setextent.html
   sandbox/ahocevar/playground/examples/sld.html
   sandbox/ahocevar/playground/examples/small.jpg
   sandbox/ahocevar/playground/examples/snap-split.html
   sandbox/ahocevar/playground/examples/snapping.html
   sandbox/ahocevar/playground/examples/spherical-mercator.html
   sandbox/ahocevar/playground/examples/split-feature.html
   sandbox/ahocevar/playground/examples/strategy-bbox.html
   sandbox/ahocevar/playground/examples/strategy-cluster-threshold.html
   sandbox/ahocevar/playground/examples/strategy-cluster.html
   sandbox/ahocevar/playground/examples/strategy-paging.html
   sandbox/ahocevar/playground/examples/style.css
   sandbox/ahocevar/playground/examples/stylemap.html
   sandbox/ahocevar/playground/examples/styles-context.html
   sandbox/ahocevar/playground/examples/styles-rotation.html
   sandbox/ahocevar/playground/examples/styles-unique.html
   sandbox/ahocevar/playground/examples/sundials-spherical-mercator.html
   sandbox/ahocevar/playground/examples/sundials.html
   sandbox/ahocevar/playground/examples/symbolizers-fill-stroke-graphic.html
   sandbox/ahocevar/playground/examples/teleportation.html
   sandbox/ahocevar/playground/examples/thinlong.jpg
   sandbox/ahocevar/playground/examples/tilecache.html
   sandbox/ahocevar/playground/examples/tms.html
   sandbox/ahocevar/playground/examples/transition.html
   sandbox/ahocevar/playground/examples/urban.html
   sandbox/ahocevar/playground/examples/ve-novibrate.html
   sandbox/ahocevar/playground/examples/ve.html
   sandbox/ahocevar/playground/examples/vector-features-with-text.html
   sandbox/ahocevar/playground/examples/vector-features.html
   sandbox/ahocevar/playground/examples/vector-formats.html
   sandbox/ahocevar/playground/examples/wfs-protocol-transactions.html
   sandbox/ahocevar/playground/examples/wfs-protocol.html
   sandbox/ahocevar/playground/examples/wfs-reprojection.html
   sandbox/ahocevar/playground/examples/wfs-snap-split.html
   sandbox/ahocevar/playground/examples/wfs-states.html
   sandbox/ahocevar/playground/examples/widelong.jpg
   sandbox/ahocevar/playground/examples/wideshort.jpg
   sandbox/ahocevar/playground/examples/wmc.html
   sandbox/ahocevar/playground/examples/wms-untiled.html
   sandbox/ahocevar/playground/examples/wms.html
   sandbox/ahocevar/playground/examples/wmst.html
   sandbox/ahocevar/playground/examples/worldwind.html
   sandbox/ahocevar/playground/examples/wrapDateLine.html
   sandbox/ahocevar/playground/examples/xhtml.html
   sandbox/ahocevar/playground/examples/xml.html
   sandbox/ahocevar/playground/examples/xyz-esri.html
   sandbox/ahocevar/playground/examples/yahoo.html
   sandbox/ahocevar/playground/examples/zoomLevels.html
   sandbox/ahocevar/playground/img/cloud-popup-relative.png
   sandbox/ahocevar/playground/lib/OpenLayers.js
   sandbox/ahocevar/playground/lib/OpenLayers/Ajax.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Bounds.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Class.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Element.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/LonLat.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Pixel.js
   sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Size.js
   sandbox/ahocevar/playground/lib/OpenLayers/Console.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ArgParser.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Attribution.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Button.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/DragFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/DragPan.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/DrawFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/EditingToolbar.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/GetFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/KeyboardDefaults.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/LayerSwitcher.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Measure.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ModifyFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseDefaults.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/MousePosition.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseToolbar.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/NavToolbar.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Navigation.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/NavigationHistory.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/OverviewMap.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Pan.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/PanPanel.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoom.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoomBar.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Panel.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Permalink.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Scale.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ScaleLine.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/SelectFeature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Snapping.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/Split.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/WMSGetFeatureInfo.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomBox.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomIn.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomOut.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomPanel.js
   sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomToMaxExtent.js
   sandbox/ahocevar/playground/lib/OpenLayers/Events.js
   sandbox/ahocevar/playground/lib/OpenLayers/Feature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Feature/Vector.js
   sandbox/ahocevar/playground/lib/OpenLayers/Feature/WFS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Filter.js
   sandbox/ahocevar/playground/lib/OpenLayers/Filter/Comparison.js
   sandbox/ahocevar/playground/lib/OpenLayers/Filter/FeatureId.js
   sandbox/ahocevar/playground/lib/OpenLayers/Filter/Logical.js
   sandbox/ahocevar/playground/lib/OpenLayers/Filter/Spatial.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML/Features.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/Base.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v2.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v3.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GPX.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoJSON.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoRSS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/JSON.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/KML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/OSM.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/Text.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSDescribeFeatureType.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WKT.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSGetFeatureInfo.js
   sandbox/ahocevar/playground/lib/OpenLayers/Format/XML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Collection.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Curve.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LineString.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LinearRing.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiLineString.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPoint.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPolygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Point.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Polygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Rectangle.js
   sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Surface.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Box.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Click.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Drag.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Feature.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Hover.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Keyboard.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/MouseWheel.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Path.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Point.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/Polygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Handler/RegularPolygon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Icon.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/ca.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/cs-CZ.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/da-DK.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/de.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/en-CA.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/en.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/es.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/fr.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/it.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/nb.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/nl.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt-BR.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/sv-SE.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-CN.js
   sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-TW.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcGIS93Rest.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcIMS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Boxes.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/EventPane.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/FixedZoomLevels.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/GML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/GeoRSS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Grid.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/HTTPRequest.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Image.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMap.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMapCache.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapGuide.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer/Untiled.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Markers.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/MultiMap.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/PointTrack.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/SphericalMercator.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/TMS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Text.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/TileCache.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector/RootContainer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/VirtualEarth.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WFS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Untiled.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/WorldWind.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/XYZ.js
   sandbox/ahocevar/playground/lib/OpenLayers/Layer/Yahoo.js
   sandbox/ahocevar/playground/lib/OpenLayers/Map.js
   sandbox/ahocevar/playground/lib/OpenLayers/Marker.js
   sandbox/ahocevar/playground/lib/OpenLayers/Marker/Box.js
   sandbox/ahocevar/playground/lib/OpenLayers/Popup.js
   sandbox/ahocevar/playground/lib/OpenLayers/Popup/Anchored.js
   sandbox/ahocevar/playground/lib/OpenLayers/Popup/AnchoredBubble.js
   sandbox/ahocevar/playground/lib/OpenLayers/Popup/Framed.js
   sandbox/ahocevar/playground/lib/OpenLayers/Popup/FramedCloud.js
   sandbox/ahocevar/playground/lib/OpenLayers/Projection.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/HTTP.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL/Gears.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_0_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_1_0.js
   sandbox/ahocevar/playground/lib/OpenLayers/Renderer.js
   sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Canvas.js
   sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Elements.js
   sandbox/ahocevar/playground/lib/OpenLayers/Renderer/SVG.js
   sandbox/ahocevar/playground/lib/OpenLayers/Renderer/VML.js
   sandbox/ahocevar/playground/lib/OpenLayers/Request.js
   sandbox/ahocevar/playground/lib/OpenLayers/Request/XMLHttpRequest.js
   sandbox/ahocevar/playground/lib/OpenLayers/Rule.js
   sandbox/ahocevar/playground/lib/OpenLayers/SingleFile.js
   sandbox/ahocevar/playground/lib/OpenLayers/Strategy.js
   sandbox/ahocevar/playground/lib/OpenLayers/Strategy/
   sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Fixed.js
   sandbox/ahocevar/playground/lib/OpenLayers/Style.js
   sandbox/ahocevar/playground/lib/OpenLayers/StyleMap.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tile.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tile/WFS.js
   sandbox/ahocevar/playground/lib/OpenLayers/Tween.js
   sandbox/ahocevar/playground/lib/OpenLayers/Util.js
   sandbox/ahocevar/playground/license.txt
   sandbox/ahocevar/playground/news.txt
   sandbox/ahocevar/playground/readme.txt
   sandbox/ahocevar/playground/release-license.txt
   sandbox/ahocevar/playground/tests/BaseTypes.html
   sandbox/ahocevar/playground/tests/BaseTypes/Element.html
   sandbox/ahocevar/playground/tests/BaseTypes/LonLat.html
   sandbox/ahocevar/playground/tests/Control.html
   sandbox/ahocevar/playground/tests/Control/Attribution.html
   sandbox/ahocevar/playground/tests/Control/DragPan.html
   sandbox/ahocevar/playground/tests/Control/DrawFeature.html
   sandbox/ahocevar/playground/tests/Control/GetFeature.html
   sandbox/ahocevar/playground/tests/Control/LayerSwitcher.html
   sandbox/ahocevar/playground/tests/Control/Measure.html
   sandbox/ahocevar/playground/tests/Control/ModifyFeature.html
   sandbox/ahocevar/playground/tests/Control/MousePosition.html
   sandbox/ahocevar/playground/tests/Control/Navigation.html
   sandbox/ahocevar/playground/tests/Control/NavigationHistory.html
   sandbox/ahocevar/playground/tests/Control/OverviewMap.html
   sandbox/ahocevar/playground/tests/Control/PanZoom.html
   sandbox/ahocevar/playground/tests/Control/PanZoomBar.html
   sandbox/ahocevar/playground/tests/Control/Panel.html
   sandbox/ahocevar/playground/tests/Control/ScaleLine.html
   sandbox/ahocevar/playground/tests/Control/SelectFeature.html
   sandbox/ahocevar/playground/tests/Control/WMSGetFeatureInfo.html
   sandbox/ahocevar/playground/tests/Feature.html
   sandbox/ahocevar/playground/tests/Feature/Vector.html
   sandbox/ahocevar/playground/tests/Filter/Comparison.html
   sandbox/ahocevar/playground/tests/Filter/Logical.html
   sandbox/ahocevar/playground/tests/Filter/Spatial.html
   sandbox/ahocevar/playground/tests/Format/Filter/
   sandbox/ahocevar/playground/tests/Format/GML.html
   sandbox/ahocevar/playground/tests/Format/GML/v2.html
   sandbox/ahocevar/playground/tests/Format/GML/v3.html
   sandbox/ahocevar/playground/tests/Format/GPX.html
   sandbox/ahocevar/playground/tests/Format/GeoJSON.html
   sandbox/ahocevar/playground/tests/Format/KML.html
   sandbox/ahocevar/playground/tests/Format/OSM.html
   sandbox/ahocevar/playground/tests/Format/SLD/v1_0_0.html
   sandbox/ahocevar/playground/tests/Format/WFSCapabilities/v1.html
   sandbox/ahocevar/playground/tests/Format/WFST/v1.html
   sandbox/ahocevar/playground/tests/Format/WFST/v1_0_0.html
   sandbox/ahocevar/playground/tests/Format/WFST/v1_1_0.html
   sandbox/ahocevar/playground/tests/Format/WKT.html
   sandbox/ahocevar/playground/tests/Format/WMC.html
   sandbox/ahocevar/playground/tests/Format/WMC/v1.html
   sandbox/ahocevar/playground/tests/Format/WMC/v1_1_0.html
   sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_1_1.html
   sandbox/ahocevar/playground/tests/Format/WMSDescribeLayer.html
   sandbox/ahocevar/playground/tests/Format/WMSGetFeatureInfo.html
   sandbox/ahocevar/playground/tests/Format/XML.html
   sandbox/ahocevar/playground/tests/Geometry.html
   sandbox/ahocevar/playground/tests/Geometry/Collection.html
   sandbox/ahocevar/playground/tests/Geometry/LinearRing.html
   sandbox/ahocevar/playground/tests/Handler/Drag.html
   sandbox/ahocevar/playground/tests/Handler/MouseWheel.html
   sandbox/ahocevar/playground/tests/Handler/Polygon.html
   sandbox/ahocevar/playground/tests/Layer.html
   sandbox/ahocevar/playground/tests/Layer/ArcGIS93Rest.html
   sandbox/ahocevar/playground/tests/Layer/ArcIMS.html
   sandbox/ahocevar/playground/tests/Layer/EventPane.html
   sandbox/ahocevar/playground/tests/Layer/GeoRSS.html
   sandbox/ahocevar/playground/tests/Layer/Google.html
   sandbox/ahocevar/playground/tests/Layer/Grid.html
   sandbox/ahocevar/playground/tests/Layer/HTTPRequest.html
   sandbox/ahocevar/playground/tests/Layer/Image.html
   sandbox/ahocevar/playground/tests/Layer/MapServer.html
   sandbox/ahocevar/playground/tests/Layer/MultiMap.html
   sandbox/ahocevar/playground/tests/Layer/SphericalMercator.html
   sandbox/ahocevar/playground/tests/Layer/TMS.html
   sandbox/ahocevar/playground/tests/Layer/Text.html
   sandbox/ahocevar/playground/tests/Layer/Vector.html
   sandbox/ahocevar/playground/tests/Layer/WFS.html
   sandbox/ahocevar/playground/tests/Layer/WMS.html
   sandbox/ahocevar/playground/tests/Layer/XYZ.html
   sandbox/ahocevar/playground/tests/Map.html
   sandbox/ahocevar/playground/tests/Marker/Box.html
   sandbox/ahocevar/playground/tests/Popup.html
   sandbox/ahocevar/playground/tests/Popup/Anchored.html
   sandbox/ahocevar/playground/tests/Projection.html
   sandbox/ahocevar/playground/tests/Protocol.html
   sandbox/ahocevar/playground/tests/Protocol/HTTP.html
   sandbox/ahocevar/playground/tests/Protocol/WFS.html
   sandbox/ahocevar/playground/tests/Renderer/Canvas.html
   sandbox/ahocevar/playground/tests/Renderer/Elements.html
   sandbox/ahocevar/playground/tests/Renderer/SVG.html
   sandbox/ahocevar/playground/tests/Renderer/VML.html
   sandbox/ahocevar/playground/tests/Request.html
   sandbox/ahocevar/playground/tests/Rule.html
   sandbox/ahocevar/playground/tests/Strategy/
   sandbox/ahocevar/playground/tests/Strategy/Fixed.html
   sandbox/ahocevar/playground/tests/Style.html
   sandbox/ahocevar/playground/tests/Tile/Image.html
   sandbox/ahocevar/playground/tests/Util.html
   sandbox/ahocevar/playground/tests/data/geos_wkt_intersects.js
   sandbox/ahocevar/playground/tests/list-tests.html
   sandbox/ahocevar/playground/tests/manual/clip-features-svg.html
   sandbox/ahocevar/playground/tests/manual/google-panning.html
   sandbox/ahocevar/playground/tests/manual/tiles-loading.html
   sandbox/ahocevar/playground/tests/manual/ve-opacity.html
   sandbox/ahocevar/playground/tests/run-tests.html
   sandbox/ahocevar/playground/tests/speed/
   sandbox/ahocevar/playground/tests/throws.js
   sandbox/ahocevar/playground/theme/default/google.css
   sandbox/ahocevar/playground/theme/default/ie6-style.css
   sandbox/ahocevar/playground/theme/default/img/pan-panel-NOALPHA.png
   sandbox/ahocevar/playground/theme/default/img/pan-panel.png
   sandbox/ahocevar/playground/theme/default/img/zoom-panel-NOALPHA.png
   sandbox/ahocevar/playground/theme/default/img/zoom-panel.png
   sandbox/ahocevar/playground/theme/default/style.css
   sandbox/ahocevar/playground/tools/exampleparser.py
   sandbox/ahocevar/playground/tools/mergejs.py
   sandbox/ahocevar/playground/tools/update_dev_dir.sh
Log:
merging r10919 from trunk



Property changes on: sandbox/ahocevar/playground
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/openlayers:7571-9424
   + /sandbox/roberthl/openlayers:9745-9748
/trunk/openlayers:7565-10919

Modified: sandbox/ahocevar/playground/apidoc_config/Menu.txt
===================================================================
--- sandbox/ahocevar/playground/apidoc_config/Menu.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/apidoc_config/Menu.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -74,6 +74,7 @@
       File: DrawFeature  (no auto-title, OpenLayers/Control/DrawFeature.js)
       File: EditingToolbar  (no auto-title, OpenLayers/Control/EditingToolbar.js)
       File: GetFeature  (no auto-title, OpenLayers/Control/GetFeature.js)
+      File: Graticule  (OpenLayers/Control/Graticule.js)
       File: KeyboardDefaults  (no auto-title, OpenLayers/Control/KeyboardDefaults.js)
       File: LayerSwitcher  (no auto-title, OpenLayers/Control/LayerSwitcher.js)
       File: Measure  (no auto-title, OpenLayers/Control/Measure.js)
@@ -96,6 +97,7 @@
       File: SelectFeature  (no auto-title, OpenLayers/Control/SelectFeature.js)
       File: Snapping  (no auto-title, OpenLayers/Control/Snapping.js)
       File: Split  (no auto-title, OpenLayers/Control/Split.js)
+      File: WMSGetFeatureInfo  (OpenLayers/Control/WMSGetFeatureInfo.js)
       File: ZoomBox  (no auto-title, OpenLayers/Control/ZoomBox.js)
       File: ZoomIn  (no auto-title, OpenLayers/Control/ZoomIn.js)
       File: ZoomOut  (no auto-title, OpenLayers/Control/ZoomOut.js)
@@ -124,6 +126,13 @@
    Group: Format  {
 
       File: Format  (no auto-title, OpenLayers/Format.js)
+      File: ArcXML  (no auto-title, OpenLayers/Format/ArcXML.js)
+      File: ArcXML.Features  (no auto-title, OpenLayers/Format/ArcXML/Features.js)
+      File: Atom  (no auto-title, OpenLayers/Format/Atom.js)
+      File: CSWGetDomain.DEFAULTS  (no auto-title, OpenLayers/Format/CSWGetDomain.js)
+      File: CSWGetDomain.v2_0_2  (no auto-title, OpenLayers/Format/CSWGetDomain/v2_0_2.js)
+      File: CSWGetRecords.DEFAULTS  (no auto-title, OpenLayers/Format/CSWGetRecords.js)
+      File: CSWGetRecords.v2_0_2  (no auto-title, OpenLayers/Format/CSWGetRecords/v2_0_2.js)
 
       Group: Filter  {
 
@@ -133,6 +142,9 @@
          File: v1_1_0  (OpenLayers/Format/Filter/v1_1_0.js)
          }  # Group: Filter
 
+      File: GeoJSON  (no auto-title, OpenLayers/Format/GeoJSON.js)
+      File: GeoRSS  (no auto-title, OpenLayers/Format/GeoRSS.js)
+
       Group: GML  {
 
          File: GML  (no auto-title, OpenLayers/Format/GML.js)
@@ -141,6 +153,12 @@
          File: v3  (no auto-title, OpenLayers/Format/GML/v3.js)
          }  # Group: GML
 
+      File: GPX  (no auto-title, OpenLayers/Format/GPX.js)
+      File: JSON  (no auto-title, OpenLayers/Format/JSON.js)
+      File: KML  (no auto-title, OpenLayers/Format/KML.js)
+      File: OSM  (no auto-title, OpenLayers/Format/OSM.js)
+      File: OWSCommon.v1_1_0  (OpenLayers/Format/OWSCommon/v1_1_0.js)
+
       Group: SLD  {
 
          File: SLD  (no auto-title, OpenLayers/Format/SLD.js)
@@ -148,6 +166,32 @@
          File: v1_0_0  (no auto-title, OpenLayers/Format/SLD/v1_0_0.js)
          }  # Group: SLD
 
+      File: SOSCapabilities  (OpenLayers/Format/SOSCapabilities.js)
+      File: SOSCapabilities.v1_0_0  (OpenLayers/Format/SOSCapabilities/v1_0_0.js)
+      File: SOSGetObservation  (OpenLayers/Format/SOSGetObservation.js)
+      File: Text  (no auto-title, OpenLayers/Format/Text.js)
+      File: WFS  (no auto-title, OpenLayers/Format/WFS.js)
+
+      Group: WFSCapabilities  {
+
+         File: WFSCapabilities  (no auto-title, OpenLayers/Format/WFSCapabilities.js)
+         File: v1  (no auto-title, OpenLayers/Format/WFSCapabilities/v1.js)
+         File: v1_0_0  (no auto-title, OpenLayers/Format/WFSCapabilities/v1_0_0.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Format/WFSCapabilities/v1_1_0.js)
+         }  # Group: WFSCapabilities
+
+      File: WFSDescribeFeatureType  (no auto-title, OpenLayers/Format/WFSDescribeFeatureType.js)
+
+      Group: WFST  {
+
+         File: WFST  (no auto-title, OpenLayers/Format/WFST.js)
+         File: v1  (OpenLayers/Format/WFST/v1.js)
+         File: v1_0_0  (OpenLayers/Format/WFST/v1_0_0.js)
+         File: v1_1_0  (OpenLayers/Format/WFST/v1_1_0.js)
+         }  # Group: WFST
+
+      File: WKT  (no auto-title, OpenLayers/Format/WKT.js)
+
       Group: WMC  {
 
          File: WMC  (no auto-title, OpenLayers/Format/WMC.js)
@@ -156,33 +200,25 @@
          File: v1_1_0  (no auto-title, OpenLayers/Format/WMC/v1_1_0.js)
          }  # Group: WMC
 
-      Group: Format  {
+      Group: WMSCapabilities  {
 
-         File: GeoJSON  (no auto-title, OpenLayers/Format/GeoJSON.js)
-         File: GeoRSS  (no auto-title, OpenLayers/Format/GeoRSS.js)
-         File: GPX  (no auto-title, OpenLayers/Format/GPX.js)
-         File: JSON  (no auto-title, OpenLayers/Format/JSON.js)
-         File: KML  (no auto-title, OpenLayers/Format/KML.js)
-         File: OSM  (no auto-title, OpenLayers/Format/OSM.js)
-         File: Text  (no auto-title, OpenLayers/Format/Text.js)
-         File: WFS  (no auto-title, OpenLayers/Format/WFS.js)
-         File: WFSDescribeFeatureType  (OpenLayers/Format/WFSDescribeFeatureType.js)
+         File: WMSCapabilities  (no auto-title, OpenLayers/Format/WMSCapabilities.js)
+         File: v1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1.js)
+         File: v1_1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1_0.js)
+         File: v1_1_1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1_1.js)
+         File: v1_3  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_3.js)
+         File: v1_3_0  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_3_0.js)
+         }  # Group: WMSCapabilities
 
-         Group: WFST  {
+      Group: WMSDescribeLayer  {
 
-            File: WFST  (no auto-title, OpenLayers/Format/WFST.js)
-            File: v1  (OpenLayers/Format/WFST/v1.js)
-            File: v1_0_0  (OpenLayers/Format/WFST/v1_0_0.js)
-            File: v1_1_0  (OpenLayers/Format/WFST/v1_1_0.js)
-            }  # Group: WFST
+         File: WMSDescribeLayer  (no auto-title, OpenLayers/Format/WMSDescribeLayer.js)
+         File: v1_1  (no auto-title, OpenLayers/Format/WMSDescribeLayer/v1_1.js)
+         }  # Group: WMSDescribeLayer
 
-         File: WKT  (no auto-title, OpenLayers/Format/WKT.js)
-         File: WMSDescribeLayer  (OpenLayers/Format/WMSDescribeLayer.js)
-         File: WMSDescribeLayer.v1_1  (OpenLayers/Format/WMSDescribeLayer/v1_1.js)
-         File: WMSGetFeatureInfo  (OpenLayers/Format/WMSGetFeatureInfo.js)
-         File: XML  (no auto-title, OpenLayers/Format/XML.js)
-         }  # Group: Format
-
+      File: WMSGetFeatureInfo  (no auto-title, OpenLayers/Format/WMSGetFeatureInfo.js)
+      File: XML  (no auto-title, OpenLayers/Format/XML.js)
       }  # Group: Format
 
    Group: Geometry  {
@@ -221,6 +257,10 @@
    Group: Lang  {
 
       File: Lang  (no auto-title, OpenLayers/Lang.js)
+      File: ar  (no auto-title, OpenLayers/Lang/ar.js)
+      File: be-tarask  (no auto-title, OpenLayers/Lang/be-tarask.js)
+      File: bg  (no auto-title, OpenLayers/Lang/bg.js)
+      File: br  (no auto-title, OpenLayers/Lang/br.js)
       File: ca  (no auto-title, OpenLayers/Lang/ca.js)
       File: cs-CZ  (no auto-title, OpenLayers/Lang/cs-CZ.js)
       File: da-DK  (no auto-title, OpenLayers/Lang/da-DK.js)
@@ -228,12 +268,35 @@
       File: en  (no auto-title, OpenLayers/Lang/en.js)
       File: en-CA  (no auto-title, OpenLayers/Lang/en-CA.js)
       File: es  (no auto-title, OpenLayers/Lang/es.js)
+      File: el  (no auto-title, OpenLayers/Lang/el.js)
+      File: fi  (no auto-title, OpenLayers/Lang/fi.js)
       File: fr  (no auto-title, OpenLayers/Lang/fr.js)
+      File: fur  (no auto-title, OpenLayers/Lang/fur.js)
+      File: gl  (no auto-title, OpenLayers/Lang/gl.js)
+      File: gsw  (no auto-title, OpenLayers/Lang/gsw.js)
+      File: hr  (no auto-title, OpenLayers/Lang/hr.js)
+      File: hsb  (no auto-title, OpenLayers/Lang/hsb.js)
+      File: hu  (no auto-title, OpenLayers/Lang/hu.js)
+      File: ia  (no auto-title, OpenLayers/Lang/ia.js)
+      File: id  (no auto-title, OpenLayers/Lang/id.js)
+      File: io  (no auto-title, OpenLayers/Lang/io.js)
+      File: is  (no auto-title, OpenLayers/Lang/is.js)
       File: it  (no auto-title, OpenLayers/Lang/it.js)
+      File: ja  (no auto-title, OpenLayers/Lang/ja.js)
+      File: km  (no auto-title, OpenLayers/Lang/km.js)
+      File: ksh  (no auto-title, OpenLayers/Lang/ksh.js)
+      File: nds  (no auto-title, OpenLayers/Lang/nds.js)
       File: nb  (no auto-title, OpenLayers/Lang/nb.js)
       File: nl  (no auto-title, OpenLayers/Lang/nl.js)
+      File: nn  (no auto-title, OpenLayers/Lang/nn.js)
+      File: oc  (no auto-title, OpenLayers/Lang/oc.js)
+      File: pt  (no auto-title, OpenLayers/Lang/pt.js)
       File: pt-BR  (no auto-title, OpenLayers/Lang/pt-BR.js)
+      File: ru  (no auto-title, OpenLayers/Lang/ru.js)
+      File: sk  (no auto-title, OpenLayers/Lang/sk.js)
       File: sv-SE  (no auto-title, OpenLayers/Lang/sv-SE.js)
+      File: te  (no auto-title, OpenLayers/Lang/te.js)
+      File: vi  (no auto-title, OpenLayers/Lang/vi.js)
       File: zh-CN  (no auto-title, OpenLayers/Lang/zh-CN.js)
       File: zh-TW  (no auto-title, OpenLayers/Lang/zh-TW.js)
       }  # Group: Lang
@@ -242,6 +305,7 @@
 
       File: Layer  (no auto-title, OpenLayers/Layer.js)
       File: ArcGIS93Rest  (no auto-title, OpenLayers/Layer/ArcGIS93Rest.js)
+      File: ArcIMS  (no auto-title, OpenLayers/Layer/ArcIMS.js)
       File: Boxes  (no auto-title, OpenLayers/Layer/Boxes.js)
       File: EventPane  (no auto-title, OpenLayers/Layer/EventPane.js)
       File: FixedZoomLevels  (no auto-title, OpenLayers/Layer/FixedZoomLevels.js)
@@ -264,13 +328,15 @@
       File: TileCache  (no auto-title, OpenLayers/Layer/TileCache.js)
       File: TMS  (no auto-title, OpenLayers/Layer/TMS.js)
       File: Vector  (no auto-title, OpenLayers/Layer/Vector.js)
-      File: RootContainer  (OpenLayers/Layer/Vector/RootContainer.js)
+      File: Vector.RootContainer  (no auto-title, OpenLayers/Layer/Vector/RootContainer.js)
       File: VirtualEarth  (no auto-title, OpenLayers/Layer/VirtualEarth.js)
       File: WFS  (no auto-title, OpenLayers/Layer/WFS.js)
       File: WMS  (no auto-title, OpenLayers/Layer/WMS.js)
       File: WMS.Untiled  (no auto-title, OpenLayers/Layer/WMS/Untiled.js)
+      File: WMS.Post  (no auto-title, OpenLayers/Layer/WMS/Post.js)
       File: WorldWind  (no auto-title, OpenLayers/Layer/WorldWind.js)
       File: Yahoo  (no auto-title, OpenLayers/Layer/Yahoo.js)
+      File: XYZ  (no auto-title, OpenLayers/Layer/XYZ.js)
       }  # Group: Layer
 
    File: Map  (no auto-title, OpenLayers/Map.js)
@@ -306,9 +372,9 @@
       Group: WFS  {
 
          File: WFS  (no auto-title, OpenLayers/Protocol/WFS.js)
-         File: v1  (OpenLayers/Protocol/WFS/v1.js)
-         File: v1_0_0  (OpenLayers/Protocol/WFS/v1_0_0.js)
-         File: v1_1_0  (OpenLayers/Protocol/WFS/v1_1_0.js)
+         File: v1  (no auto-title, OpenLayers/Protocol/WFS/v1.js)
+         File: v1_0_0  (no auto-title, OpenLayers/Protocol/WFS/v1_0_0.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Protocol/WFS/v1_1_0.js)
          }  # Group: WFS
 
       }  # Group: Protocol
@@ -337,6 +403,7 @@
       File: Cluster  (no auto-title, OpenLayers/Strategy/Cluster.js)
       File: Fixed  (no auto-title, OpenLayers/Strategy/Fixed.js)
       File: Paging  (no auto-title, OpenLayers/Strategy/Paging.js)
+      File: Refresh  (OpenLayers/Strategy/Refresh.js)
       File: Save  (OpenLayers/Strategy/Save.js)
       }  # Group: Strategy
 
@@ -348,6 +415,7 @@
       File: Tile  (no auto-title, OpenLayers/Tile.js)
       File: Image  (no auto-title, OpenLayers/Tile/Image.js)
       File: WFS  (no auto-title, OpenLayers/Tile/WFS.js)
+      File: IFrame  (OpenLayers/Tile/Image/IFrame.js)
       }  # Group: Tile
 
    File: Tween  (no auto-title, OpenLayers/Tween.js)

Modified: sandbox/ahocevar/playground/build/build.py
===================================================================
--- sandbox/ahocevar/playground/build/build.py	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/build/build.py	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,47 +4,51 @@
 sys.path.append("../tools")
 import mergejs
 
-have_compressor = None
-try:
-    import jsmin
-    have_compressor = "jsmin"
-except ImportError:
+def build():
+    have_compressor = None
     try:
-        import minimize
-        have_compressor = "minimize"
-    except Exception, E:
-        print E
-        pass
+        import jsmin
+        have_compressor = "jsmin"
+    except ImportError:
+        try:
+            import minimize
+            have_compressor = "minimize"
+        except Exception, E:
+            print E
+            pass
 
-sourceDirectory = "../lib"
-configFilename = "full.cfg"
-outputFilename = "OpenLayers.js"
+    sourceDirectory = "../lib"
+    configFilename = "full.cfg"
+    outputFilename = "OpenLayers.js"
 
-if len(sys.argv) > 1:
-    configFilename = sys.argv[1]
-    extension = configFilename[-4:]
+    if len(sys.argv) > 1:
+        configFilename = sys.argv[1]
+        extension = configFilename[-4:]
 
-    if extension  != ".cfg":
-        configFilename = sys.argv[1] + ".cfg"
+        if extension  != ".cfg":
+            configFilename = sys.argv[1] + ".cfg"
 
-if len(sys.argv) > 2:
-    outputFilename = sys.argv[2]
+    if len(sys.argv) > 2:
+        outputFilename = sys.argv[2]
 
-print "Merging libraries."
-merged = mergejs.run(sourceDirectory, None, configFilename)
-if have_compressor == "jsmin":
-    print "Compressing using jsmin."
-    minimized = jsmin.jsmin(merged)
-elif have_compressor == "minimize":
-    print "Compressing using minimize."
-    minimized = minimize.minimize(merged)
-else: # fallback
-    print "Not compressing."
-    minimized = merged 
-print "Adding license file."
-minimized = file("license.txt").read() + minimized
+    print "Merging libraries."
+    merged = mergejs.run(sourceDirectory, None, configFilename)
+    if have_compressor == "jsmin":
+        print "Compressing using jsmin."
+        minimized = jsmin.jsmin(merged)
+    elif have_compressor == "minimize":
+        print "Compressing using minimize."
+        minimized = minimize.minimize(merged)
+    else: # fallback
+        print "Not compressing."
+        minimized = merged 
+    print "Adding license file."
+    minimized = file("license.txt").read() + minimized
 
-print "Writing to %s." % outputFilename
-file(outputFilename, "w").write(minimized)
+    print "Writing to %s." % outputFilename
+    file(outputFilename, "w").write(minimized)
 
-print "Done."
+    print "Done."
+
+if __name__ == '__main__':
+  build()
\ No newline at end of file

Modified: sandbox/ahocevar/playground/build/full.cfg
===================================================================
--- sandbox/ahocevar/playground/build/full.cfg	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/build/full.cfg	2010-11-28 15:48:59 UTC (rev 10920)
@@ -3,7 +3,6 @@
 
 [first]
 OpenLayers/SingleFile.js
-OpenLayers.js
 OpenLayers/BaseTypes.js
 OpenLayers/BaseTypes/Class.js
 OpenLayers/Util.js
@@ -14,19 +13,6 @@
 [include]
 
 [exclude]
-Firebug/firebug.js
-Firebug/firebugx.js
-OpenLayers/Lang/ca.js
-OpenLayers/Lang/cs-CZ.js
-OpenLayers/Lang/da-DK.js
-OpenLayers/Lang/de.js
-OpenLayers/Lang/en-CA.js
-OpenLayers/Lang/es.js
-OpenLayers/Lang/fr.js
-OpenLayers/Lang/it.js
-OpenLayers/Lang/nb.js
-OpenLayers/Lang/nl.js
-OpenLayers/Lang/pt-BR.js
-OpenLayers/Lang/sv-SE.js
-OpenLayers/Lang/zh-TW.js
-OpenLayers/Lang/zh-CN.js
+Firebug
+OpenLayers.js
+OpenLayers/Lang

Modified: sandbox/ahocevar/playground/build/library.cfg
===================================================================
--- sandbox/ahocevar/playground/build/library.cfg	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/build/library.cfg	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,7 +4,6 @@
 
 [first]
 OpenLayers/SingleFile.js
-OpenLayers.js
 OpenLayers/BaseTypes.js
 OpenLayers/BaseTypes/Class.js
 OpenLayers/Util.js
@@ -15,8 +14,8 @@
 [include]
 
 [exclude]
-Firebug/firebug.js
-Firebug/firebugx.js
+Firebug
+OpenLayers.js
 OpenLayers/Format/GeoRSS.js
 OpenLayers/Format/GML.js
 OpenLayers/Format/WKT.js
@@ -50,19 +49,6 @@
 OpenLayers/Renderer/SVG.js
 OpenLayers/Renderer/VML.js
 OpenLayers/Renderer.js
-OpenLayers/Lang/ca.js
-OpenLayers/Lang/cs-CZ.js
-OpenLayers/Lang/da-DK.js
-OpenLayers/Lang/de.js
-OpenLayers/Lang/en-CA.js
-OpenLayers/Lang/es.js
-OpenLayers/Lang/fr.js
-OpenLayers/Lang/it.js
-OpenLayers/Lang/nb.js
-OpenLayers/Lang/nl.js
-OpenLayers/Lang/pt-BR.js
-OpenLayers/Lang/sv-SE.js
-OpenLayers/Lang/zh-TW.js
-OpenLayers/Lang/zh-CN.js
+OpenLayers/Lang
 
 

Modified: sandbox/ahocevar/playground/build/license.txt
===================================================================
--- sandbox/ahocevar/playground/build/license.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/build/license.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,8 +2,8 @@
 
   OpenLayers.js -- OpenLayers Map Viewer Library
 
-  Copyright 2005-2008 MetaCarta, Inc., released under the Clear BSD license.
-  Please see http://svn.openlayers.org/trunk/openlayers/license.txt
+  Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD
+  license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt
   for the full text of the license.
 
   Includes compressed code under the following licenses:
@@ -90,3 +90,36 @@
  * issues. Applications that use the code below will continue to work seamlessly
  * when that happens.
  */
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
\ No newline at end of file

Modified: sandbox/ahocevar/playground/build/lite.cfg
===================================================================
--- sandbox/ahocevar/playground/build/lite.cfg	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/build/lite.cfg	2010-11-28 15:48:59 UTC (rev 10920)
@@ -6,7 +6,6 @@
 
 [first]
 OpenLayers/SingleFile.js
-OpenLayers.js
 OpenLayers/BaseTypes.js
 OpenLayers/BaseTypes/Class.js
 OpenLayers/Util.js

Modified: sandbox/ahocevar/playground/doc_config/Menu.txt
===================================================================
--- sandbox/ahocevar/playground/doc_config/Menu.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/doc_config/Menu.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -74,6 +74,7 @@
       File: DrawFeature  (no auto-title, OpenLayers/Control/DrawFeature.js)
       File: EditingToolbar  (no auto-title, OpenLayers/Control/EditingToolbar.js)
       File: GetFeature  (no auto-title, OpenLayers/Control/GetFeature.js)
+      File: Graticule  (OpenLayers/Control/Graticule.js)
       File: KeyboardDefaults  (no auto-title, OpenLayers/Control/KeyboardDefaults.js)
       File: LayerSwitcher  (no auto-title, OpenLayers/Control/LayerSwitcher.js)
       File: Measure  (no auto-title, OpenLayers/Control/Measure.js)
@@ -96,6 +97,7 @@
       File: SelectFeature  (no auto-title, OpenLayers/Control/SelectFeature.js)
       File: Snapping  (no auto-title, OpenLayers/Control/Snapping.js)
       File: Split  (no auto-title, OpenLayers/Control/Split.js)
+      File: WMSGetFeatureInfo  (OpenLayers/Control/WMSGetFeatureInfo.js)
       File: ZoomBox  (no auto-title, OpenLayers/Control/ZoomBox.js)
       File: ZoomIn  (no auto-title, OpenLayers/Control/ZoomIn.js)
       File: ZoomOut  (no auto-title, OpenLayers/Control/ZoomOut.js)
@@ -124,6 +126,13 @@
    Group: Format  {
 
       File: Format  (no auto-title, OpenLayers/Format.js)
+      File: ArcXML  (no auto-title, OpenLayers/Format/ArcXML.js)
+      File: ArcXML.Features  (no auto-title, OpenLayers/Format/ArcXML/Features.js)
+      File: Atom  (no auto-title, OpenLayers/Format/Atom.js)
+      File: CSWGetDomain.DEFAULTS  (no auto-title, OpenLayers/Format/CSWGetDomain.js)
+      File: CSWGetDomain.v2_0_2  (no auto-title, OpenLayers/Format/CSWGetDomain/v2_0_2.js)
+      File: CSWGetRecords.DEFAULTS  (no auto-title, OpenLayers/Format/CSWGetRecords.js)
+      File: CSWGetRecords.v2_0_2  (no auto-title, OpenLayers/Format/CSWGetRecords/v2_0_2.js)
 
       Group: Filter  {
 
@@ -133,6 +142,9 @@
          File: v1_1_0  (OpenLayers/Format/Filter/v1_1_0.js)
          }  # Group: Filter
 
+      File: GeoJSON  (no auto-title, OpenLayers/Format/GeoJSON.js)
+      File: GeoRSS  (no auto-title, OpenLayers/Format/GeoRSS.js)
+
       Group: GML  {
 
          File: GML  (no auto-title, OpenLayers/Format/GML.js)
@@ -141,6 +153,12 @@
          File: v3  (no auto-title, OpenLayers/Format/GML/v3.js)
          }  # Group: GML
 
+      File: GPX  (no auto-title, OpenLayers/Format/GPX.js)
+      File: JSON  (no auto-title, OpenLayers/Format/JSON.js)
+      File: KML  (no auto-title, OpenLayers/Format/KML.js)
+      File: OSM  (no auto-title, OpenLayers/Format/OSM.js)
+      File: OWSCommon.v1_1_0  (OpenLayers/Format/OWSCommon/v1_1_0.js)
+
       Group: SLD  {
 
          File: SLD  (no auto-title, OpenLayers/Format/SLD.js)
@@ -148,6 +166,32 @@
          File: v1_0_0  (no auto-title, OpenLayers/Format/SLD/v1_0_0.js)
          }  # Group: SLD
 
+      File: SOSCapabilities  (OpenLayers/Format/SOSCapabilities.js)
+      File: SOSCapabilities.v1_0_0  (OpenLayers/Format/SOSCapabilities/v1_0_0.js)
+      File: SOSGetObservation  (OpenLayers/Format/SOSGetObservation.js)
+      File: Text  (no auto-title, OpenLayers/Format/Text.js)
+      File: WFS  (no auto-title, OpenLayers/Format/WFS.js)
+
+      Group: WFSCapabilities  {
+
+         File: WFSCapabilities  (no auto-title, OpenLayers/Format/WFSCapabilities.js)
+         File: v1  (no auto-title, OpenLayers/Format/WFSCapabilities/v1.js)
+         File: v1_0_0  (no auto-title, OpenLayers/Format/WFSCapabilities/v1_0_0.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Format/WFSCapabilities/v1_1_0.js)
+         }  # Group: WFSCapabilities
+
+      File: WFSDescribeFeatureType  (no auto-title, OpenLayers/Format/WFSDescribeFeatureType.js)
+
+      Group: WFST  {
+
+         File: WFST  (no auto-title, OpenLayers/Format/WFST.js)
+         File: v1  (OpenLayers/Format/WFST/v1.js)
+         File: v1_0_0  (OpenLayers/Format/WFST/v1_0_0.js)
+         File: v1_1_0  (OpenLayers/Format/WFST/v1_1_0.js)
+         }  # Group: WFST
+
+      File: WKT  (no auto-title, OpenLayers/Format/WKT.js)
+
       Group: WMC  {
 
          File: WMC  (no auto-title, OpenLayers/Format/WMC.js)
@@ -156,33 +200,25 @@
          File: v1_1_0  (no auto-title, OpenLayers/Format/WMC/v1_1_0.js)
          }  # Group: WMC
 
-      Group: Format  {
+      Group: WMSCapabilities  {
 
-         File: GeoJSON  (no auto-title, OpenLayers/Format/GeoJSON.js)
-         File: GeoRSS  (no auto-title, OpenLayers/Format/GeoRSS.js)
-         File: GPX  (no auto-title, OpenLayers/Format/GPX.js)
-         File: JSON  (no auto-title, OpenLayers/Format/JSON.js)
-         File: KML  (no auto-title, OpenLayers/Format/KML.js)
-         File: OSM  (no auto-title, OpenLayers/Format/OSM.js)
-         File: Text  (no auto-title, OpenLayers/Format/Text.js)
-         File: WFS  (no auto-title, OpenLayers/Format/WFS.js)
-         File: WFSDescribeFeatureType.js  (OpenLayers/Format/WFSDescribeFeatureType.js)
+         File: WMSCapabilities  (no auto-title, OpenLayers/Format/WMSCapabilities.js)
+         File: v1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1.js)
+         File: v1_1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1_0.js)
+         File: v1_1_1  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_1_1.js)
+         File: v1_3  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_3.js)
+         File: v1_3_0  (no auto-title, OpenLayers/Format/WMSCapabilities/v1_3_0.js)
+         }  # Group: WMSCapabilities
 
-         Group: WFST  {
+      Group: WMSDescribeLayer  {
 
-            File: WFST  (no auto-title, OpenLayers/Format/WFST.js)
-            File: v1  (OpenLayers/Format/WFST/v1.js)
-            File: v1_0_0  (OpenLayers/Format/WFST/v1_0_0.js)
-            File: v1_1_0  (OpenLayers/Format/WFST/v1_1_0.js)
-            }  # Group: WFST
+         File: WMSDescribeLayer  (no auto-title, OpenLayers/Format/WMSDescribeLayer.js)
+         File: v1_1  (no auto-title, OpenLayers/Format/WMSDescribeLayer/v1_1.js)
+         }  # Group: WMSDescribeLayer
 
-         File: WKT  (no auto-title, OpenLayers/Format/WKT.js)
-         File: WMSDescribeLayer  (OpenLayers/Format/WMSDescribeLayer.js)
-         File: WMSDescribeLayer.v1_1  (OpenLayers/Format/WMSDescribeLayer/v1_1.js)
-         File: WMSGetFeatureInfo  (OpenLayers/Format/WMSGetFeatureInfo.js)
-         File: XML  (no auto-title, OpenLayers/Format/XML.js)
-         }  # Group: Format
-
+      File: WMSGetFeatureInfo  (no auto-title, OpenLayers/Format/WMSGetFeatureInfo.js)
+      File: XML  (no auto-title, OpenLayers/Format/XML.js)
       }  # Group: Format
 
    Group: Geometry  {
@@ -221,6 +257,10 @@
    Group: Lang  {
 
       File: Lang  (no auto-title, OpenLayers/Lang.js)
+      File: ar  (no auto-title, OpenLayers/Lang/ar.js)
+      File: be-tarask  (no auto-title, OpenLayers/Lang/be-tarask.js)
+      File: bg  (no auto-title, OpenLayers/Lang/bg.js)
+      File: br  (no auto-title, OpenLayers/Lang/br.js)
       File: ca  (no auto-title, OpenLayers/Lang/ca.js)
       File: cs-CZ  (no auto-title, OpenLayers/Lang/cs-CZ.js)
       File: da-DK  (no auto-title, OpenLayers/Lang/da-DK.js)
@@ -228,12 +268,35 @@
       File: en  (no auto-title, OpenLayers/Lang/en.js)
       File: en-CA  (no auto-title, OpenLayers/Lang/en-CA.js)
       File: es  (no auto-title, OpenLayers/Lang/es.js)
+      File: el  (no auto-title, OpenLayers/Lang/el.js)
+      File: fi  (no auto-title, OpenLayers/Lang/fi.js)
       File: fr  (no auto-title, OpenLayers/Lang/fr.js)
+      File: fur  (no auto-title, OpenLayers/Lang/fur.js)
+      File: gl  (no auto-title, OpenLayers/Lang/gl.js)
+      File: gsw  (no auto-title, OpenLayers/Lang/gsw.js)
+      File: hr  (no auto-title, OpenLayers/Lang/hr.js)
+      File: hsb  (no auto-title, OpenLayers/Lang/hsb.js)
+      File: hu  (no auto-title, OpenLayers/Lang/hu.js)
+      File: ia  (no auto-title, OpenLayers/Lang/ia.js)
+      File: id  (no auto-title, OpenLayers/Lang/id.js)
+      File: io  (no auto-title, OpenLayers/Lang/io.js)
+      File: is  (no auto-title, OpenLayers/Lang/is.js)
       File: it  (no auto-title, OpenLayers/Lang/it.js)
+      File: ja  (no auto-title, OpenLayers/Lang/ja.js)
+      File: km  (no auto-title, OpenLayers/Lang/km.js)
+      File: ksh  (no auto-title, OpenLayers/Lang/ksh.js)
+      File: nds  (no auto-title, OpenLayers/Lang/nds.js)
       File: nb  (no auto-title, OpenLayers/Lang/nb.js)
       File: nl  (no auto-title, OpenLayers/Lang/nl.js)
+      File: nn  (no auto-title, OpenLayers/Lang/nn.js)
+      File: oc  (no auto-title, OpenLayers/Lang/oc.js)
+      File: pt  (no auto-title, OpenLayers/Lang/pt.js)
       File: pt-BR  (no auto-title, OpenLayers/Lang/pt-BR.js)
+      File: ru  (no auto-title, OpenLayers/Lang/ru.js)
+      File: sk  (no auto-title, OpenLayers/Lang/sk.js)
       File: sv-SE  (no auto-title, OpenLayers/Lang/sv-SE.js)
+      File: te  (no auto-title, OpenLayers/Lang/te.js)
+      File: vi  (no auto-title, OpenLayers/Lang/vi.js)
       File: zh-CN  (no auto-title, OpenLayers/Lang/zh-CN.js)
       File: zh-TW  (no auto-title, OpenLayers/Lang/zh-TW.js)
       }  # Group: Lang
@@ -242,6 +305,7 @@
 
       File: Layer  (no auto-title, OpenLayers/Layer.js)
       File: ArcGIS93Rest  (no auto-title, OpenLayers/Layer/ArcGIS93Rest.js)
+      File: ArcIMS  (no auto-title, OpenLayers/Layer/ArcIMS.js)
       File: Boxes  (no auto-title, OpenLayers/Layer/Boxes.js)
       File: EventPane  (no auto-title, OpenLayers/Layer/EventPane.js)
       File: FixedZoomLevels  (no auto-title, OpenLayers/Layer/FixedZoomLevels.js)
@@ -264,13 +328,15 @@
       File: TileCache  (no auto-title, OpenLayers/Layer/TileCache.js)
       File: TMS  (no auto-title, OpenLayers/Layer/TMS.js)
       File: Vector  (no auto-title, OpenLayers/Layer/Vector.js)
-      File: RootContainer  (OpenLayers/Layer/Vector/RootContainer.js)
+      File: Vector.RootContainer  (no auto-title, OpenLayers/Layer/Vector/RootContainer.js)
       File: VirtualEarth  (no auto-title, OpenLayers/Layer/VirtualEarth.js)
       File: WFS  (no auto-title, OpenLayers/Layer/WFS.js)
       File: WMS  (no auto-title, OpenLayers/Layer/WMS.js)
       File: WMS.Untiled  (no auto-title, OpenLayers/Layer/WMS/Untiled.js)
+      File: WMS.Post  (no auto-title, OpenLayers/Layer/WMS/Post.js)
       File: WorldWind  (no auto-title, OpenLayers/Layer/WorldWind.js)
       File: Yahoo  (no auto-title, OpenLayers/Layer/Yahoo.js)
+      File: XYZ  (no auto-title, OpenLayers/Layer/XYZ.js)
       }  # Group: Layer
 
    File: Map  (no auto-title, OpenLayers/Map.js)
@@ -306,9 +372,9 @@
       Group: WFS  {
 
          File: WFS  (no auto-title, OpenLayers/Protocol/WFS.js)
-         File: v1  (OpenLayers/Protocol/WFS/v1.js)
-         File: v1_0_0  (OpenLayers/Protocol/WFS/v1_0_0.js)
-         File: v1_1_0  (OpenLayers/Protocol/WFS/v1_1_0.js)
+         File: v1  (no auto-title, OpenLayers/Protocol/WFS/v1.js)
+         File: v1_0_0  (no auto-title, OpenLayers/Protocol/WFS/v1_0_0.js)
+         File: v1_1_0  (no auto-title, OpenLayers/Protocol/WFS/v1_1_0.js)
          }  # Group: WFS
 
       }  # Group: Protocol
@@ -337,6 +403,7 @@
       File: Cluster  (no auto-title, OpenLayers/Strategy/Cluster.js)
       File: Fixed  (no auto-title, OpenLayers/Strategy/Fixed.js)
       File: Paging  (no auto-title, OpenLayers/Strategy/Paging.js)
+      File: Refresh  (OpenLayers/Strategy/Refresh.js)
       File: Save  (OpenLayers/Strategy/Save.js)
       }  # Group: Strategy
 
@@ -348,6 +415,7 @@
       File: Tile  (no auto-title, OpenLayers/Tile.js)
       File: Image  (no auto-title, OpenLayers/Tile/Image.js)
       File: WFS  (no auto-title, OpenLayers/Tile/WFS.js)
+      File: IFrame  (OpenLayers/Tile/Image/IFrame.js)
       }  # Group: Tile
 
    File: Tween  (no auto-title, OpenLayers/Tween.js)

Modified: sandbox/ahocevar/playground/examples/GMLParser.html
===================================================================
--- sandbox/ahocevar/playground/examples/GMLParser.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/GMLParser.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -27,7 +27,9 @@
   <body onload="load()">
       <h1 id="title">GML Parser Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        GML, parse, parsing
+      </div>
 
       <p id="shortdesc">
           Demonstrate the operation of the GML parser.

Modified: sandbox/ahocevar/playground/examples/Jugl.js
===================================================================
--- sandbox/ahocevar/playground/examples/Jugl.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/Jugl.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,84 +1,8 @@
-/**
+/*
  * Jugl.js -- JavaScript Template Library
  *
- * Copyright 2007 Tim Schaub
- * Released under the MIT license.  Please see
- * http://svn.tschaub.net/jugl/trunk/license.txt for the full license.
+ * Copyright 2007-2010 Tim Schaub
+ * Released under the MIT license.  Please see 
+ * http://github.com/tschaub/jugl/blob/master/license.txt for the full license.
  */
-
-(function(){var Jugl={prefix:"jugl",namespaceURI:"http://namespace.jugl.org/"};Jugl.Array={indexOf:function(array,obj){for(var i=0;i<array.length;i++){if(array[i]==obj)return i;}
-return-1;}};Jugl.Function={bind:function(method,object){var args=[];for(var i=2;i<arguments.length;++i){args.push(arguments[i]);}
-return function(){for(var i=0;i<arguments.length;++i){args.push(arguments[i]);}
-return method.apply(object,args);}}};Jugl.Node={appendChild:function(parent,child){if(typeof(parent)=="string"){var obj=document.getElementById(parent);if(!obj){throw Error("Element id not found: "+parent);}
-parent=obj;}
-if(typeof(child)=="string"){var obj=document.getElementById(child);if(!obj){throw Error("Element id not found: "+child);}
-child=obj;}
-if(child.namespaceURI&&child.xml){var wrapper=document.createElement('div');wrapper.innerHTML=child.xml;var children=wrapper.childNodes;for(var i=0;i<children.length;++i){parent.appendChild(children[i]);}}else{if(parent.ownerDocument&&parent.ownerDocument.importNode){child=parent.ownerDocument.importNode(child,true);}
-parent.appendChild(child);}
-return child;}};Jugl.Object={extend:function(destination,source){destination=destination||{};source=source||{};for(property in source){destination[property]=source[property];}
-return destination;},applyDefaults:function(destination,source){destination=destination||{};source=source||{};for(property in source){if(destination[property]===undefined){destination[property]=source[property];}}
-return destination;}};Jugl.Request={loadTemplate:function(url,onComplete,caller){var createTemplate=function(request){var doc,template;try{doc=request.responseXML;template=new Jugl.Template(doc.documentElement);}catch(invalidXML){try{doc=document.createElement("div");doc.innerHTML=request.responseText;template=new Jugl.Template(doc.firstChild);}catch(invalidHTML){var msg="Can't make HTML out of response: "+
-request.responseText;Jugl.Console.error(msg);throw invalidHTML;}}
-var complete=Jugl.Function.bind(onComplete,caller);complete(template);}
-Jugl.Request.loadUrl(url,createTemplate);},loadUrl:function(url,onComplete,caller){var complete=(caller)?Jugl.Function.bind(onComplete,caller):onComplete;var request=Jugl.Request.createXMLHttpRequest();request.open("GET",url);request.onreadystatechange=function(){if(request.readyState==4){complete(request);}}
-request.send(null);},createXMLHttpRequest:function(){if(typeof XMLHttpRequest!="undefined"){return new XMLHttpRequest();}else if(typeof ActiveXObject!="undefined"){return new ActiveXObject("Microsoft.XMLHTTP");}else{throw new Error("XMLHttpRequest not supported");}}};Jugl.Class=function(){var Class=function(){if(this===Jugl){var msg="Create an instance of a Jugl "+"class with the new keyword";throw Error(msg);}
-this.initialize.apply(this,arguments);}
-var extended={toString:function(){return"["+this.CLASS_NAME+"]";}};var parent;for(var i=0;i<arguments.length;++i){if(typeof arguments[i]=="function"){parent=arguments[i].prototype;}else{parent=arguments[i];}
-Jugl.Object.extend(extended,parent);}
-Class.prototype=extended;return Class;};Jugl.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){}};(function(){if(window.console){var scripts=document.getElementsByTagName("script");for(var i=0;i<scripts.length;++i){if(scripts[i].src.indexOf("firebug.js")!=-1){Jugl.Object.extend(Jugl.Console,console);break;}}}})();Jugl.Attribute=Jugl.Class({element:null,node:null,type:null,nodeValue:null,template:null,initialize:function(element,node,type){this.element=element;this.node=node;this.type=type;this.nodeValue=node.nodeValue;this.nodeName=node.nodeName;this.template=element.template;},splitAttributeValue:function(value){value=(value!=null)?value:this.nodeValue;var matches=this.template.regExes.trimSpace.exec(value);var
  items;if(matches&&matches.length==3){items=[matches[1],matches[2]];}
-return items;},splitExpressionPrefix:function(){var items=this.splitAttributeValue();if(!items||(items[0]!='structure'&&items[0]!='text')){items=[null,this.nodeValue];}
-return items;},getAttributeValues:function(){var trimmed=this.nodeValue.replace(/[\t\n]/g,"").replace(/;\s*$/,"");var tabbed=trimmed.replace(/;;/g,"\t");var newlined=tabbed.split(";").join("\n");return newlined.replace(/\t/g,";").split(/\n/g);},removeSelf:function(){this.element.removeAttributeNode(this);},process:function(){return this.processAttribute[this.type].apply(this,[]);},evalInScope:function(str){var expression="with(this.element.scope){"+str+"}";return eval(expression);},processAttribute:{"define":function(){var values=this.getAttributeValues();var pair;for(var i=0;i<values.length;++i){pair=this.splitAttributeValue(values[i]);this.element.scope[pair[0]]=this.evalInScope(pair[1]);}
-this.removeSelf();return true;},"condition":function(){var proceed;try{proceed=!!(this.evalInScope(this.nodeValue));}catch(err){var message=err.name+": "+err.message+"\n"+"attribute: "+this.nodeName;Jugl.Console.error(message);throw err;}
-this.removeSelf();if(!proceed){this.element.removeSelf();}
-return proceed;},"repeat":function(){var pair=this.splitAttributeValue();var key=pair[0];var list=this.evalInScope(pair[1]);this.removeSelf();if(!(list instanceof Array)){var items=new Array();for(var p in list){items.push(p);}
-list=items;}
-var element;var previousSibling=this.element;var length=list.length;for(var i=0;i<length;++i){element=this.element.clone();element.scope[key]=list[i];element.scope.repeat[key]={index:i,number:i+1,even:!(i%2),odd:!!(i%2),start:(i==0),end:(i==length-1),length:length};previousSibling.insertAfter(element);element.process();previousSibling=element;}
-this.element.removeSelf();return false;},"content":function(){var pair=this.splitExpressionPrefix();var str;try{str=this.evalInScope(pair[1]);}catch(err){Jugl.Console.error("Failed to eval in element scope: "+
-pair[1]);throw err;}
-this.removeSelf();if(pair[0]=='structure'){try{this.element.node.innerHTML=str;}catch(err){var wrapper=document.createElement('div');var msg;try{wrapper.innerHTML=str;}catch(invalidHTML){msg="Can't transform string into valid HTML : "+
-str;Jugl.Console.error(msg);throw invalidHTML;}
-if(this.element.node.xml&&this.template.xmldom){while(this.element.node.firstChild){this.element.node.removeChild(this.element.node.firstChild);}
-this.template.xmldom.loadXML(wrapper.outerHTML);var children=this.template.xmldom.firstChild.childNodes;try{for(var i=0;i<children.length;++i){this.element.node.appendChild(children[i]);}}catch(invalidXML){msg="Can't transform string into valid XHTML : "+
-str;Jugl.Console.error(msg);throw invalidXML;}}else{try{this.element.node.innerHTML=wrapper.innerHTML;}catch(invalidXML){msg="Can't transform string into valid XHTML : "+
-str;Jugl.Console.error(msg);throw invalidXML;}}}}else{var text;if(this.element.node.xml&&this.template.xmldom){text=this.template.xmldom.createTextNode(str);}else{text=document.createTextNode(str);}
-var child=new Jugl.Element(this.template,text);this.element.removeChildNodes();this.element.appendChild(child);}
-return true;},"replace":function(){var pair=this.splitExpressionPrefix();var str;try{str=this.evalInScope(pair[1]);}catch(err){Jugl.Console.error("Failed to eval in element scope: "+
-pair[1]);throw err;}
-this.removeSelf();if(pair[0]=='structure'){var wrapper=document.createElement('div');try{wrapper.innerHTML=str;}catch(err){msg="Can't transform string into valid HTML : "+
-str;Jugl.Console.error(msg);throw err;}
-if(this.element.node.xml&&this.template.xmldom){try{this.template.xmldom.loadXML(wrapper.outerHTML);}catch(err){msg="Can't transform string into valid XML : "+
-str;Jugl.Console.error(msg);throw err;}
-wrapper=this.template.xmldom.firstChild;}
-while(wrapper.firstChild){var child=wrapper.removeChild(wrapper.firstChild);if(this.element.node.ownerDocument&&this.element.node.ownerDocument.importNode){if(child.ownerDocument!=this.element.node.ownerDocument){child=this.element.node.ownerDocument.importNode(child,true);}}
-this.element.node.parentNode.insertBefore(child,this.element.node);}}else{var text;if(this.element.node.xml&&this.template.xmldom){text=this.template.xmldom.createTextNode(str);}else{text=document.createTextNode(str);}
-var replacement=new Jugl.Element(this.template,text);this.element.insertBefore(replacement);}
-this.element.removeSelf();return true;},"attributes":function(){var values=this.getAttributeValues();var pair,name,value;for(var i=0;i<values.length;++i){pair=this.splitAttributeValue(values[i]);name=pair[0];value=this.evalInScope(pair[1]);if(value!==false){this.element.setAttribute(name,value);}}
-this.removeSelf();return true;},"omit-tag":function(){var omit;try{omit=((this.nodeValue=="")||!!(this.evalInScope(this.nodeValue)));}catch(err){Jugl.Console.error("Failed to eval in element scope: "+
-this.nodeValue);throw err;}
-this.removeSelf();if(omit){var children=this.element.getChildNodes();var child;for(var i=0;i<children.length;++i){this.element.insertBefore(children[i]);}
-this.element.removeSelf();}},"reflow":function(){var reflow;try{reflow=((this.nodeValue=="")||!!(this.evalInScope(this.nodeValue)));}catch(err){Jugl.Console.error("Failed to eval in element scope: "+
-this.nodeValue);throw err;}
-this.removeSelf();if(reflow){if(this.element.node.outerHTML){this.element.node.outerHTML=this.element.node.outerHTML;}else{this.element.node.innerHTML=this.element.node.innerHTML;}}}},CLASS_NAME:"Jugl.Attribute"});Jugl.Element=Jugl.Class({template:null,node:null,scope:null,initialize:function(template,node){this.template=template;this.node=node;this.scope=new Object();this.scope.repeat=new Object();},clone:function(){var node=this.node.cloneNode(true);node.removeAttribute("id");var element=new Jugl.Element(this.template,node);Jugl.Object.extend(element.scope,this.scope);return element;},getAttribute:function(localName){var node;if(this.node.nodeType==1){if(this.template.usingNS){node=this.node.getAttributeNodeNS(Jugl.namespaceURI,localName);}else{node=this.node.getAttributeNode(Jugl.prefix+":"+
-localName);}
-if(node&&!node.specified){node=false;}}
-var attribute;if(node){attribute=new Jugl.Attribute(this,node,localName);}else{attribute=node;}
-return attribute;},setAttribute:function(name,value){this.node.setAttribute(name,value);},removeAttributeNode:function(attribute){this.node.removeAttributeNode(attribute.node);},getChildNodes:function(){var numNodes=this.node.childNodes.length;var children=new Array(numNodes);var node,scope;for(var i=0;i<numNodes;++i){node=new Jugl.Element(this.template,this.node.childNodes[i]);node.scope=Jugl.Object.extend({},this.scope);children[i]=node;}
-return children;},removeChildNodes:function(){while(this.node.hasChildNodes()){this.node.removeChild(this.node.firstChild);}},removeChild:function(element){this.node.removeChild(element.node);return node;},removeSelf:function(){this.node.parentNode.removeChild(this.node);},importNode:function(element){if(this.node.ownerDocument&&this.node.ownerDocument.importNode){if(element.node.ownerDocument!=this.node.ownerDocument){element.node=this.node.ownerDocument.importNode(element.node,true);}}},appendChild:function(element){this.importNode(element);this.node.appendChild(element.node);},insertAfter:function(element){this.importNode(element);var parent=this.node.parentNode;var sibling=this.node.nextSibling;if(sibling){parent.insertBefore(element.node,sibling);}else{parent.appendChild(element.node);}},insertBefore:function(element){this.importNode(element);var parent=this.node.parentNode;parent.insertBefore(element.node,this.node);},process:function(){var attribute;var keepProcessing
 =true;var series=["define","condition","repeat"];for(var i=0;i<series.length;++i){attribute=this.getAttribute(series[i]);if(attribute){try{keepProcessing=attribute.process();}catch(err){Jugl.Console.error("Failed to process "+
-series[i]+" attribute");throw err;}
-if(!keepProcessing){return;}}}
-var content=this.getAttribute("content");if(content){try{content.process();}catch(err){Jugl.Console.error("Failed to process content attribute");throw err;}}else{var replace=this.getAttribute("replace");if(replace){try{replace.process();}catch(err){Jugl.Console.error("Failed to process replace attribute");throw err;}}}
-var attributes=this.getAttribute("attributes");if(attributes){try{attributes.process();}catch(err){Jugl.Console.error("Failed to process attributes attribute");throw err;}}
-if(!content&&!replace){this.processChildNodes();}
-var omit=this.getAttribute("omit-tag");if(omit){try{omit.process();}catch(err){Jugl.Console.error("Failed to process omit-tag attribute");throw err;}}
-var reflow=this.getAttribute("reflow");if(reflow){try{reflow.process();}catch(err){Jugl.Console.error("Failed to process reflow attribute");throw err;}}},processChildNodes:function(){var children=this.getChildNodes();for(var i=0;i<children.length;++i){try{children[i].process();}catch(err){Jugl.Console.error("Failed to process child node: "+i);throw err;}}},CLASS_NAME:"Jugl.Element"});Jugl.Template=Jugl.Class({node:null,usingNS:false,xhtmlns:"http://www.w3.org/1999/xhtml",xmldom:window.ActiveXObject?new ActiveXObject("Microsoft.XMLDOM"):null,regExes:{trimSpace:(/^\s*(\w+)\s+(.*?)\s*$/)},loaded:false,loading:false,initialize:function(config){if(typeof config=="string"||(config&&config.nodeType==1)){config={node:config};}
-config=config||{};if(typeof(config.node)=="string"){config.node=document.getElementById(config.node);if(!config.node){throw Error("Element id not found: "+config.node);}}
-if(config.node){this.node=config.node;this.loaded=true;}else if(config.url){this.load({url:config.url,callback:config.callback,scope:config.scope});}},process:function(config){if(config&&!config.context&&!config.clone&&!config.string&&!config.parent){config={context:config}}
-config=Jugl.Object.applyDefaults(config,{context:null,clone:false,string:false});if(this.node.getAttributeNodeNS){if(this.node.getAttributeNodeNS(Jugl.xhtmlns,Jugl.prefix)){this.usingNS=true;}}
-var element=new Jugl.Element(this,this.node);if(config.clone){element=element.clone();}
-if(config.context){element.scope=config.context;}
-try{element.process();}catch(err){Jugl.Console.error("Failed to process "+
-this.node.nodeName+" node");throw err;}
-var data;if(config.string){if(element.node.innerHTML){data=element.node.innerHTML;}else{if(this.xmldom){data=element.node.xml;}else{var serializer=new XMLSerializer();data=serializer.serializeToString(element.node);}}}else{data=element.node;if(config.parent){if(config.clone){data=Jugl.Node.appendChild(config.parent,element.node);}else{this.appendTo(config.parent);}}}
-return data;},load:function(config){if(typeof config=="string"){config={url:config};}
-config=config||{};this.loading=true;var setNode=function(template){this.node=template.node;this.loading=false;this.loaded=true;if(config.callback){config.callback.apply(config.scope,[template]);}}
-Jugl.Request.loadTemplate(config.url,setNode,this);},appendTo:function(parent){this.node=Jugl.Node.appendChild(parent,this.node);return this;},CLASS_NAME:"Jugl.Template"});window["http://jugl.tschaub.net/trunk/lib/Jugl.js"]=Jugl;})();
\ No newline at end of file
+(function(){var f={prefix:"jugl",namespaceURI:null,loadTemplate:function(h){var i=function(l){var m,k,n=!l.status||(l.status>=200&&l.status<300);if(n){try{m=l.responseXML;k=new e(m.documentElement)}catch(j){m=document.createElement("div");m.innerHTML=l.responseText;k=new e(m.firstChild)}if(h.callback){h.callback.call(h.scope,k)}}else{if(h.failure){h.failure.call(h.scope,l)}}};d(h.url,i)}};var g=function(h,j){h=h||{};j=j||{};for(var i in j){h[i]=j[i]}return h};var a=function(l,o){var m,n,k,j,h;if(typeof(l)==="string"){m=document.getElementById(l);if(!m){throw Error("Element id not found: "+l)}l=m}if(typeof(o)==="string"){m=document.getElementById(o);if(!m){throw Error("Element id not found: "+o)}o=m}if(o.namespaceURI&&o.xml){n=document.createElement("div");n.innerHTML=o.xml;k=n.childNodes;for(j=0,h=k.length;j<h;++j){l.appendChild(k[j])}}else{if(l.ownerDocument&&l.ownerDocument.importNode&&l.ownerDocument!==o.ownerDocument){o=l.ownerDocument.importNode(o,true)}l.appendChild(o)
 }return o};var d=function(h,k,i){var j;if(typeof XMLHttpRequest!=="undefined"){j=new XMLHttpRequest()}else{if(typeof ActiveXObject!=="undefined"){j=new ActiveXObject("Microsoft.XMLHTTP")}else{throw new Error("XMLHttpRequest not supported")}}j.open("GET",h);j.onreadystatechange=function(){if(j.readyState===4){k.call(i,j)}};j.send(null)};var b=function(h,i){this.template=h;this.node=i;this.scope={};this.scope.repeat={}};g(b.prototype,{clone:function(){var i=this.node.cloneNode(true);i.removeAttribute("id");var h=new b(this.template,i);g(h.scope,this.scope);return h},getAttribute:function(h){var j;if(this.node.nodeType===1){if(this.template.usingNS){j=this.node.getAttributeNodeNS(f.namespaceURI,h)}else{j=this.node.getAttributeNode(f.prefix+":"+h)}if(j&&!j.specified){j=false}}var i;if(j){i=new c(this,j,h)}else{i=j}return i},setAttribute:function(h,i){this.node.setAttribute(h,i)},removeAttributeNode:function(h){this.node.removeAttributeNode(h.node)},getChildNodes:function(){var k
 =this.node.childNodes.length;var j=new Array(k);var l;for(var h=0;h<k;++h){l=new b(this.template,this.node.childNodes[h]);l.scope=g({},this.scope);j[h]=l}return j},removeChildNodes:function(){while(this.node.hasChildNodes()){this.node.removeChild(this.node.firstChild)}},removeChild:function(h){this.node.removeChild(h.node);return node},removeSelf:function(){this.node.parentNode.removeChild(this.node)},importNode:function(h){if(this.node.ownerDocument&&this.node.ownerDocument.importNode){if(h.node.ownerDocument!==this.node.ownerDocument){h.node=this.node.ownerDocument.importNode(h.node,true)}}},appendChild:function(h){this.importNode(h);this.node.appendChild(h.node)},insertAfter:function(h){this.importNode(h);var j=this.node.parentNode;var i=this.node.nextSibling;if(i){j.insertBefore(h.node,i)}else{j.appendChild(h.node)}},insertBefore:function(h){this.importNode(h);var i=this.node.parentNode;i.insertBefore(h.node,this.node)},process:function(){var j;var r=true;var n=["define"
 ,"condition","repeat"];for(var o=0,p=n.length;o<p;++o){j=this.getAttribute(n[o]);if(j){r=j.process();if(!r){return}}}var q=this.getAttribute("content");if(q){q.process()}else{var k=this.getAttribute("replace");if(k){k.process()}}var m=this.getAttribute("attributes");if(m){m.process()}if(!q&&!k){this.processChildNodes()}var h=this.getAttribute("omit-tag");if(h){h.process()}var l=this.getAttribute("reflow");if(l){l.process()}},processChildNodes:function(){var k=this.getChildNodes();for(var j=0,h=k.length;j<h;++j){k[j].process()}}});var e=function(h){h=h||{};if(typeof h==="string"||(h.nodeType===1)){h={node:h}}if(typeof(h.node)==="string"){h.node=document.getElementById(h.node);if(!h.node){throw Error("Element id not found: "+h.node)}}if(h.node){this.node=h.node;this.loaded=true}else{if(h.url){this.load({url:h.url,callback:h.callback,scope:h.scope})}}};g(e.prototype,{node:null,usingNS:false,xmldom:window.ActiveXObject?new ActiveXObject("Microsoft.XMLDOM"):null,trimSpace:(/^\s*(
 \w+)\s+(.*?)\s*$/),loaded:false,loading:false,process:function(h){var i,j;h=g({context:null,clone:false,string:false},h);this.usingNS=this.node.getAttributeNodeNS&&f.namespaceURI;i=new b(this,this.node);if(h.clone||h.string){i=i.clone()}if(h.context){i.scope=h.context}i.process();if(h.string){if(i.node.innerHTML){j=i.node.innerHTML}else{if(this.xmldom){j=i.node.xml}else{j=(new XMLSerializer).serializeToString(i.node)}}}else{j=i.node;if(h.parent){if(h.clone){j=a(h.parent,i.node)}else{this.appendTo(h.parent)}}}return j},load:function(j){if(typeof j==="string"){j={url:j}}j=j||{};this.loading=true;var h=function(k){this.node=k.node;this.loading=false;this.loaded=true;if(j.callback){j.callback.apply(j.scope,[k])}};var i;if(j.failure){i=(function(){return function(k){j.failure.call(j.scope,k)}})()}f.loadTemplate({url:j.url,callback:h,failure:i,scope:this})},appendTo:function(h){this.node=a(h,this.node);return this}});var c=function(h,j,i){this.element=h;this.node=j;this.type=i;thi
 s.nodeValue=j.nodeValue;this.nodeName=j.nodeName;this.template=h.template};g(c.prototype,{splitAttributeValue:function(i){i=(i!=null)?i:this.nodeValue;var h=this.template.trimSpace.exec(i);return h&&h.length===3&&[h[1],h[2]]},splitExpressionPrefix:function(){var h=this.splitAttributeValue();if(!h||(h[0]!="structure"&&h[0]!="text")){h=[null,this.nodeValue]}return h},getAttributeValues:function(){return this.nodeValue.replace(/[\t\n]/g,"").replace(/;\s*$/,"").replace(/;;/g,"\t").split(";").join("\n").replace(/\t/g,";").split(/\n/g)},removeSelf:function(){this.element.removeAttributeNode(this)},process:function(){return this.processAttribute[this.type].apply(this,[])},evalInScope:function(k){var i=this.element.scope;var h=[];var j=[];for(key in i){h.push(key);j.push(i[key])}var l=new Function(h.join(","),"return "+k);return l.apply({},j)},processAttribute:{define:function(){var l,k,j,h=this.getAttributeValues();for(k=0,j=h.length;k<j;++k){l=this.splitAttributeValue(h[k]);this.e
 lement.scope[l[0]]=this.evalInScope(l[1])}this.removeSelf();return true},condition:function(){var h=!!(this.evalInScope(this.nodeValue));this.removeSelf();if(!h){this.element.removeSelf()}return h},repeat:function(){var l=this.splitAttributeValue();var r=l[0];var o=this.evalInScope(l[1]);this.removeSelf();if(!(o instanceof Array)){var q=new Array();for(var j in o){q.push(j)}o=q}var m;var h=this.element;for(var n=0,k=o.length;n<k;++n){m=this.element.clone();m.scope[r]=o[n];m.scope.repeat[r]={index:n,number:n+1,even:!(n%2),odd:!!(n%2),start:(n===0),end:(n===k-1),length:k};h.insertAfter(m);m.process();h=m}this.element.removeSelf();return false},content:function(){var m=this.splitExpressionPrefix();var p=this.evalInScope(m[1]);this.removeSelf();if(m[0]==="structure"){try{this.element.node.innerHTML=p}catch(l){var h=document.createElement("div");h.innerHTML=p;if(this.element.node.xml&&this.template.xmldom){while(this.element.node.firstChild){this.element.node.removeChild(this.ele
 ment.node.firstChild)}this.template.xmldom.loadXML(h.outerHTML);var k=this.template.xmldom.firstChild.childNodes;for(var n=0,o=k.length;n<o;++n){this.element.node.appendChild(k[n])}}else{this.element.node.innerHTML=h.innerHTML}}}else{var q;if(this.element.node.xml&&this.template.xmldom){q=this.template.xmldom.createTextNode(p)}else{q=document.createTextNode(p)}var j=new b(this.template,q);this.element.removeChildNodes();this.element.appendChild(j)}return true},replace:function(){var k=this.splitExpressionPrefix();var j=this.evalInScope(k[1]);this.removeSelf();if(k[0]==="structure"){var m=document.createElement("div");m.innerHTML=j;if(this.element.node.xml&&this.template.xmldom){this.template.xmldom.loadXML(m.outerHTML);m=this.template.xmldom.firstChild}while(m.firstChild){var l=m.removeChild(m.firstChild);if(this.element.node.ownerDocument&&this.element.node.ownerDocument.importNode){if(l.ownerDocument!=this.element.node.ownerDocument){l=this.element.node.ownerDocument.impor
 tNode(l,true)}}this.element.node.parentNode.insertBefore(l,this.element.node)}}else{var i;if(this.element.node.xml&&this.template.xmldom){i=this.template.xmldom.createTextNode(j)}else{i=document.createTextNode(j)}var h=new b(this.template,i);this.element.insertBefore(h)}this.element.removeSelf();return true},attributes:function(){var h=this.getAttributeValues();var n,k,m;for(var l=0,j=h.length;l<j;++l){n=this.splitAttributeValue(h[l]);k=n[0];m=this.evalInScope(n[1]);if(m!==false){this.element.setAttribute(k,m)}}this.removeSelf();return true},"omit-tag":function(){var l=((this.nodeValue==="")||!!(this.evalInScope(this.nodeValue)));this.removeSelf();if(l){var k=this.element.getChildNodes();for(var j=0,h=k.length;j<h;++j){this.element.insertBefore(k[j])}this.element.removeSelf()}},reflow:function(){var h=((this.nodeValue==="")||!!(this.evalInScope(this.nodeValue)));this.removeSelf();if(h){if(this.element.node.outerHTML){this.element.node.outerHTML=this.element.node.outerHTML}el
 se{this.element.node.innerHTML=this.element.node.innerHTML}}}}});window.jugl=g(f,{Template:e})})();
\ No newline at end of file

Modified: sandbox/ahocevar/playground/examples/KMLParser.html
===================================================================
--- sandbox/ahocevar/playground/examples/KMLParser.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/KMLParser.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -31,7 +31,9 @@
   <body onload="load()">
       <h1 id="title">KML Parser Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        KML, parsing, format
+      </div>
 
       <p id="shortdesc">
           Demonstrate the operation of the KML parser.

Copied: sandbox/ahocevar/playground/examples/SLDSelect.html (from rev 10919, trunk/openlayers/examples/SLDSelect.html)
===================================================================
--- sandbox/ahocevar/playground/examples/SLDSelect.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/SLDSelect.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,198 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers SLD based selection control</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <style type="text/css">
+        .olControlSLDSelectBoxActive {
+            cursor: crosshair;
+        }
+        .olControlSLDSelectPolygonActive {
+            cursor: crosshair;
+        }
+        .olControlSLDSelectLineActive {
+            cursor: crosshair;
+        }
+        .olControlSLDSelectPointActive {
+            cursor: pointer;
+        }
+    </style>
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, controls, layers;
+
+        function init(){
+            OpenLayers.ProxyHost= "proxy.cgi?url=";
+            map = new OpenLayers.Map('map', {allOverlays: true, controls: []});
+            var url = "http://demo.opengeo.org/geoserver/wms";
+            layers = {
+                states: new OpenLayers.Layer.WMS("State boundary", url,
+                    {layers: 'topp:tasmania_state_boundaries', format: 'image/gif', transparent: 'TRUE'},
+                    {singleTile: true}),
+                roads: new OpenLayers.Layer.WMS("Roads", url,
+                    {layers: 'topp:tasmania_roads', format: 'image/gif', transparent: 'TRUE'},
+                    {singleTile: true}),
+                waterbodies: new OpenLayers.Layer.WMS("Water bodies", url,
+                    {layers: 'topp:tasmania_water_bodies', format: 'image/gif', transparent: 'TRUE'},
+                    {singleTile: true}),
+                cities: new OpenLayers.Layer.WMS("Cities", url,
+                    {layers: 'topp:tasmania_cities', format: 'image/gif', transparent: 'TRUE'},
+                    {singleTile: true})
+            };
+
+            for (var key in layers) {
+                map.addLayer(layers[key]);
+            }
+
+            map.setCenter(new OpenLayers.LonLat(146.65748632815,-42.230763671875), 7);
+
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+            controls = {
+                navigation: new OpenLayers.Control.Navigation(),
+                box: new OpenLayers.Control.SLDSelect(
+                    OpenLayers.Handler.RegularPolygon,
+                    {
+                        displayClass: 'olControlSLDSelectBox', 
+                        layers: [layers['waterbodies']],
+                        handlerOptions: {irregular: true}
+                    }
+                ),
+                polygon: new OpenLayers.Control.SLDSelect(
+                    OpenLayers.Handler.Polygon,
+                    {
+                        displayClass: 'olControlSLDSelectPolygon',
+                        layers: [layers['waterbodies']]
+                    }
+                ),
+                line: new OpenLayers.Control.SLDSelect(
+                    OpenLayers.Handler.Path,
+                    {
+                        displayClass: 'olControlSLDSelectLine',
+                        layers: [layers['waterbodies']]
+                    }
+                ),
+                point: new OpenLayers.Control.SLDSelect(
+                    OpenLayers.Handler.Click,
+                    {
+                        displayClass: 'olControlSLDSelectPoint',
+                        layers: [layers['waterbodies']]
+                    }
+                ),
+                circle: new OpenLayers.Control.SLDSelect(
+                    OpenLayers.Handler.RegularPolygon,
+                    {
+                        displayClass: 'olControlSLDSelectBox',
+                        layers: [layers['waterbodies']],
+                        handlerOptions: {sides: 30}
+                    }
+                )
+            };
+
+            for(var key in controls) {
+                map.addControl(controls[key]);
+            }
+        }
+
+        function toggleControl(element) {
+            for(var key in controls) {
+                var control = controls[key];
+                if(element.value == key && element.checked) {
+                    control.activate();
+                } else {
+                    control.deactivate();
+                }
+            }
+        }
+
+        function toggleSelectionLayer(element) {
+            var selectLayers = [];
+            var elements = element.value.split("_");
+            for (var key in layers) {
+                var layer = layers[key];
+                for (var i=0, len=elements.length; i<len; i++) {
+                    var value = elements[i];
+                    if (value == key && element.checked) {
+                        selectLayers.push(layer);
+                    }
+                }
+            }
+            for (var i=0, len=this.map.controls.length; i<len; i++) {
+                var control = this.map.controls[i];
+                if (control instanceof OpenLayers.Control.SLDSelect) {
+                    control.setLayers(selectLayers);
+                }
+            }
+        }
+
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">SLD based selection on WMS layers</h1>
+
+    <div id="tags">
+        sld, sldselect, styling, style
+    </div>
+
+    <div id="shortdesc">Using Styled Layer Descriptors to make a selection on WMS layers</div>
+
+    <div id="map" style="width: 512; height: 256; border: 1px solid red;"></div>
+
+    <div id="docs">
+        This example uses the OpenLayers.Control.SLDSelect to select features in a WMS
+        layer. The features are highlighted using Styled Layer Descriptors (SLD). The
+        control supports point, box, line and polygon selection modes by configuring the
+        appriopriate handler.
+    </div>
+
+    <div id="controls">
+        <ul id="controlToggle"><b>Map Controls</b>
+            <li>
+                <input type="radio" name="control" value="navigation" id="noneToggle" onclick="toggleControl(this);" CHECKED>
+                <label for="noneToggle">navigate</label>
+            </li>
+            <li>
+                <input type="radio" name="control" value="box" id="boxToggle" onclick="toggleControl(this);">
+                <label for="boxToggle">SLD select with box</label>
+            </li>
+            <li>
+                <input type="radio" name="control" value="polygon" id="polygonToggle" onclick="toggleControl(this);">
+                <label for="polygonToggle">SLD select with polygon</label>
+            </li>
+            <li>
+                <input type="radio" name="control" value="line" id="lineToggle" onclick="toggleControl(this);">
+                <label for="lineToggle">SLD select with line</label>
+            </li>
+            <li>
+                <input type="radio" name="control" value="point" id="pointToggle" onclick="toggleControl(this);">
+                <label for="pointToggle">SLD select with point</label>
+            </li>
+            <li>
+                <input type="radio" name="control" value="circle" id="circleToggle" onclick="toggleControl(this);">
+                <label for="circleToggle">SLD select with circle</label>
+            </li>
+        </ul>
+    </div>
+    <div id="layers">
+        <ul id="layerToggle"><b>Selection layer</b>
+            <li>
+                <input type="radio" name="layer" value="waterbodies" id="waterbodiesToggle" onclick="toggleSelectionLayer(this);" CHECKED>
+                <label for="noneToggle">Water bodies</label>
+            </li>
+            <li>
+                <input type="radio" name="layer" value="cities" id="citiesToggle" onclick="toggleSelectionLayer(this);">
+                <label for="citiesToggle">Cities</label>
+            </li>
+            <li>
+                <input type="radio" name="layer" value="roads" id="roadsToggle" onclick="toggleSelectionLayer(this);">
+                <label for="roadsToggle">Roads</label>
+            </li>
+            <li>
+                <input type="radio" name="layer" value="roads_cities" id="roadsCitiesToggle" onclick="toggleSelectionLayer(this);">
+                <label for="roadsCitiesToggle">Roads and cities</label>
+            </li>
+        </ul>
+    </div>
+
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/WMSDescribeLayerParser.html
===================================================================
--- sandbox/ahocevar/playground/examples/WMSDescribeLayerParser.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/WMSDescribeLayerParser.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -25,7 +25,9 @@
   <body onload="load()">
       <h1 id="title">WMSDescribeLayer Parser Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+          wmsdescribelayer, parser, cleanup
+      </div>
 
       <p id="shortdesc">
           Demonstrate the operation of the WMSDescribeLayer parser.

Copied: sandbox/ahocevar/playground/examples/WMSPost.html (from rev 10919, trunk/openlayers/examples/WMSPost.html)
===================================================================
--- sandbox/ahocevar/playground/examples/WMSPost.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/WMSPost.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,179 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Basic WMS Example via HTTP-POST protocol</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map;
+
+        function init(){
+            var sld = '<StyledLayerDescriptor version="1.0.0">';
+                sld+= '<NamedLayer>';
+                sld+= '<Name>topp:tasmania_roads</Name>';
+                sld+= '<UserStyle>';
+                sld+= '<IsDefault>1</IsDefault>';
+                sld+= '<FeatureTypeStyle>';
+                sld+= '<Rule>';
+                sld+= '<LineSymbolizer>';
+                sld+= '<Stroke>';
+                sld+= '<CssParameter name="stroke">';
+                sld+= '<Literal>#787878</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '<CssParameter name="stroke-width">';
+                sld+= '<Literal>2</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Stroke>';
+                sld+= '</LineSymbolizer>';
+                sld+= '</Rule>';
+                sld+= '</FeatureTypeStyle>';
+                sld+= '</UserStyle>';
+                sld+= '</NamedLayer>';
+
+                sld+= '<NamedLayer>';
+                sld+= '<Name>topp:tasmania_water_bodies</Name>';
+                sld+= '<UserStyle>';
+                sld+= '<IsDefault>1</IsDefault>';
+                sld+= '<FeatureTypeStyle>';
+                sld+= '<Rule>';
+                sld+= '<LineSymbolizer>';
+                sld+= '<Stroke>';
+                sld+= '<CssParameter name="stroke">';
+                sld+= '<Literal>#4F94CD</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '<CssParameter name="stroke-width">';
+                sld+= '<Literal>3</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Stroke>';
+                sld+= '</LineSymbolizer>';
+                sld+= '<PolygonSymbolizer>';
+                sld+= '<Fill>';
+                sld+= '<CssParameter name="fill">';
+                sld+= '<Literal>#63B8FF</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Fill>';
+                sld+= '</PolygonSymbolizer>';
+                sld+= '</Rule>';
+                sld+= '</FeatureTypeStyle>';
+                sld+= '</UserStyle>';
+                sld+= '</NamedLayer>';
+
+                sld+= '<NamedLayer>';
+                sld+= '<Name>topp:tasmania_cities</Name>';
+                sld+= '<UserStyle>';
+                sld+= '<IsDefault>1</IsDefault>';
+                sld+= '<FeatureTypeStyle>';
+                sld+= '<Rule>';
+                sld+= '<PointSymbolizer>';
+                sld+= '<Graphic>';
+                sld+= '<Mark>';
+                sld+= '<WellKnownName>cross</WellKnownName>';
+                sld+= '<Fill>';
+                sld+= '<CssParameter name="fill">';
+                sld+= '<Literal>#00FF00</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Fill>';
+                sld+= '</Mark>';
+                sld+= '<Size>15</Size>';
+                sld+= '</Graphic>';
+                sld+= '</PointSymbolizer>';
+                sld+= '<TextSymbolizer>';
+                sld+= '<Label><PropertyName>CITY_NAME</PropertyName></Label>';
+                sld+= '<Font>';
+                sld+= '<SvgParameter name="font-size">15</SvgParameter>';
+                sld+= '</Font>';
+                sld+= '</TextSymbolizer>';
+                sld+= '</Rule>';
+                sld+= '</FeatureTypeStyle>';
+                sld+= '</UserStyle>';
+                sld+= '</NamedLayer>';
+
+                sld+= '<NamedLayer>';
+                sld+= '<Name>topp:tasmania_state_boundaries</Name>';
+                sld+= '<UserStyle>';
+                sld+= '<IsDefault>1</IsDefault>';
+                sld+= '<FeatureTypeStyle>';
+                sld+= '<Rule>';
+                sld+= '<PolygonSymbolizer>';
+                sld+= '<Fill>';
+                sld+= '<CssParameter name="fill">';
+                sld+= '<Literal>#8B8989</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '<CssParameter name="fill-opacity">';
+                sld+= '<Literal>0.2</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Fill>';
+                sld+= '<Stroke>';
+                sld+= '<CssParameter name="stroke">';
+                sld+= '<Literal>#FF4040</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '<CssParameter name="stroke-width">';
+                sld+= '<Literal>2</Literal>';
+                sld+= '</CssParameter>';
+                sld+= '</Stroke>';
+                sld+= '</PolygonSymbolizer>';
+                sld+= '</Rule>';
+                sld+= '</FeatureTypeStyle>';
+                sld+= '</UserStyle>';
+                sld+= '</NamedLayer>';
+
+                sld+= '</StyledLayerDescriptor>';
+
+            map = new OpenLayers.Map('map');
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+            var layer = new OpenLayers.Layer.WMS(
+                "OpenLayers WMS",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
+                {
+                    layers: 'basic'
+                }
+            );
+
+            var rcbw = new OpenLayers.Layer.WMS.Post("Roads, Cities, Boundaries, Water",
+                "http://demo.opengeo.org/geoserver/wms", 
+                {
+                    'layers': 'topp:tasmania_roads,topp:tasmania_water_bodies,topp:tasmania_state_boundaries,topp:tasmania_cities',
+                    transparent: true,
+                    format: 'image/jpeg',
+                    sld_body: sld
+                },
+                {
+                    isBaseLayer: false,
+                    unsupportedBrowsers: []
+                }
+            );
+            map.addLayers([layer, rcbw]);
+            map.setCenter(new OpenLayers.LonLat(146.65748632815,-42.230763671875), 7);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Basic WMS Example via HTTP-POST protocol with a large SLD
+    included</h1>
+
+    <div id="tags">
+        sld, advanced
+    </div>
+
+    <div id="shortdesc">Creating a WMS layer with a large SLD in the sld_body</div>
+
+    <div id="map" style="width: 512; height: 256; border: 1px solid red;"></div>
+
+    <div id="docs">
+        <p><b>Deprecated.</b> See <a href="wms-long-url.html">wms-long-url.html</a>
+            for the recommended way to avoid long URLs.</p><p>
+        This example uses a large SLD created on the client side to style a WMS
+        layer.  This example uses a WMS.Post layer which transfers data via the
+        HTTP-POST protocol. <br>
+        NOTE: Opera is not able to display transparent tiles with this layer,
+        and in some Firefox browsers can appear ugly viewport-shaking effects
+        while dragging arround. Use the 'unsupportedBrowsers' property to
+        control which browsers should use plain image tiles (like Layer.WMS)
+        instead. The default setting (["mozilla", "firefox", "opera"])
+        excludes problematic browsers without removing the ability to use long
+        request parameters, because all these browsers support long urls via
+        GET.</p>
+    </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/accessible.html
===================================================================
--- sandbox/ahocevar/playground/examples/accessible.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/accessible.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -38,7 +38,7 @@
                 map = new OpenLayers.Map('map', options);
                 var wms = new OpenLayers.Layer.WMS(
                     "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                     {layers: 'basic'}
                 );
                 map.addLayer(wms);
@@ -50,7 +50,8 @@
         <h1 id="title">Accessible Example</h1>
 
         <div id="tags">
-        </div>
+            keyboard, pan, panning, zoom, zooming, accesskey
+        </div>        
 
         <p id="shortdesc">
             Demonstrate how to use the KeyboardDefaults option parameter for layer types.

Copied: sandbox/ahocevar/playground/examples/all-overlays-google.html (from rev 10919, trunk/openlayers/examples/all-overlays-google.html)
===================================================================
--- sandbox/ahocevar/playground/examples/all-overlays-google.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/all-overlays-google.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers All Overlays with Google and OSM</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="all-overlays-google.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">All Overlays with Google and OSM</h1>
+        <div id="tags">
+            overlay, baselayer, google, osm, openstreetmap
+        </div>
+        <p id="shortdesc">
+            Using the Google and OSM layers as overlays.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                Using the allOverlays property on the map, the first layer added
+                must initially be visible.  This example demonstrates the use of 
+                a Google layer and an OSM layer treated as overlays.
+            </p><p>
+                See the <a href="all-overlays-google.js" target="_blank">
+                all-overlays-google.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/all-overlays-google.js (from rev 10919, trunk/openlayers/examples/all-overlays-google.js)
===================================================================
--- sandbox/ahocevar/playground/examples/all-overlays-google.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/all-overlays-google.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+var map;
+
+function init() {
+
+    map = new OpenLayers.Map({
+        div: "map",
+        allOverlays: true
+    });
+
+    var osm = new OpenLayers.Layer.OSM();
+    var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
+
+    // note that first layer must be visible
+    map.addLayers([osm, gmap]);
+
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.zoomToMaxExtent();
+
+}

Modified: sandbox/ahocevar/playground/examples/all-overlays.html
===================================================================
--- sandbox/ahocevar/playground/examples/all-overlays.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/all-overlays.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -56,6 +56,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">OpenLayers Overlays Only Example</h1>
+        <div id="tags">
+            overlay, baselayer
+        </div> 
         <p id="shortdesc">
             Demonstrates a map with overlays only.
         </p>

Modified: sandbox/ahocevar/playground/examples/animated_panning.html
===================================================================
--- sandbox/ahocevar/playground/examples/animated_panning.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/animated_panning.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -36,7 +36,7 @@
         function init(){
             map = new OpenLayers.Map('map', {numZoomLevels: 2});
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
                 
             map.addLayer(layer);
             map.zoomToMaxExtent();
@@ -47,7 +47,7 @@
 
             map2 = new OpenLayers.Map('map2', {'panMethod': null, numZoomLevels: 2} );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
                 
             map2.addLayer(layer);
             map2.zoomToMaxExtent();
@@ -73,7 +73,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">map.panTo Example</h1>
-    <div id="tags">map.panTo</div>
+    <div id="tags">
+        panning, animation, effect, smooth, panMethod
+    </div>
     <div id="shortdesc">Show animated panning effects in the map</div>
     <div id="map" class="smallmap"></div>
     <div id="docs">

Modified: sandbox/ahocevar/playground/examples/arcgis93rest.html
===================================================================
--- sandbox/ahocevar/playground/examples/arcgis93rest.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/arcgis93rest.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -41,6 +41,7 @@
     <h1 id="title">ArcGIS Server 9.3 Rest API Example</h1>
 
     <div id="tags">
+        ESRI, ArcGIS, REST, filter
     </div>
     <p id="shortdesc">
         Shows the basic use of openlayers using an ArcGIS Server 9.3 Rest API layer

Modified: sandbox/ahocevar/playground/examples/arcims-thematic.html
===================================================================
--- sandbox/ahocevar/playground/examples/arcims-thematic.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/arcims-thematic.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -44,7 +44,7 @@
             
             layer = new OpenLayers.Layer.ArcIMS(
                 "Global Sample Map",
-                "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap",
+                "http://sample.azavea.com/servlet/com.esri.esrimap.Esrimap",
                 options
             );
             map.addLayer(layer);
@@ -58,6 +58,7 @@
     <h1 id="title">ArcIMS Thematic Example</h1>
 
     <div id="tags">
+        ESRI, ArcIMS, ArcXML, style, thematic, chloropleth, representation
     </div>
     <p id="shortdesc">
         Shows the advanced use of OpenLayers using a thematic ArcIMS layer

Modified: sandbox/ahocevar/playground/examples/arcims.html
===================================================================
--- sandbox/ahocevar/playground/examples/arcims.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/arcims.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,7 +21,7 @@
             };
             
             layer = new OpenLayers.Layer.ArcIMS( "Global Sample Map",
-                    "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap", options );
+                    "http://sample.azavea.com/servlet/com.esri.esrimap.Esrimap", options );
             map.addLayer(layer);
 
             map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
@@ -33,6 +33,7 @@
     <h1 id="title">ArcIMS Example</h1>
 
     <div id="tags">
+        ESRI, ArcIMS
     </div>
     <p id="shortdesc">
         Shows the basic use of OpenLayers using an ArcIMS layer

Modified: sandbox/ahocevar/playground/examples/attribution.html
===================================================================
--- sandbox/ahocevar/playground/examples/attribution.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/attribution.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,8 +11,8 @@
                 map = new OpenLayers.Map('map');
 
                 var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'},
-                    {'attribution': 'Provided by <a href="http://labs.metacarta.com/">MetaCarta</a>'});
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'},
+                    {'attribution': 'Provided by OSGeo'});
 
                 var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
                     "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
@@ -34,7 +34,7 @@
         <h1 id="title">Attribution Example</h1>
 
         <div id="tags">
-            copyright watermark logo attribution
+            copyright, watermark, logo, attribution
         </div>
 
         <p id="shortdesc">
@@ -47,7 +47,7 @@
             This is an example of how to add an attribution block to the OpenLayers window.  In order to use an
             attribution block, an attribution parameter must be set in each layer that requires attribution. In
             addition, an attribution control must be added to the map, though one is added to all OpenLayers Maps by default. 
-            Be aware that this is a layer *option*: the options hash goes in
+            Be aware that this is a layer <strong>option</strong>: the options hash goes in
             different places depending on the layer type you are using.  
         </div>
     </body>

Modified: sandbox/ahocevar/playground/examples/baseLayers.html
===================================================================
--- sandbox/ahocevar/playground/examples/baseLayers.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/baseLayers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -15,6 +15,7 @@
         <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAA9XNhd8q0UdwNC7YSO4YZghSPUCi5aRYVveCcVYxzezM4iaj_gxQ9t-UajFL70jfcpquH5l1IJ-Zyyw'></script>
         <!-- Localhost key -->
         <!-- <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxTS6gjckBmeABOGXIUiOiZObZESPg'></script>-->
+        <!-- CLEANUP: the URL below doesn't work anymore -->
         <script type="text/javascript" src="http://clients.multimap.com/API/maps/1.1/metacarta_04"></script>
         <script src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script>
         <script src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=euzuro-openlayers"></script>
@@ -33,7 +34,7 @@
                 map = new OpenLayers.Map( 'map' );
 
                 var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                          "http://labs.metacarta.com/wms/vmap0",
+                          "http://vmap0.tiles.osgeo.org/wms/vmap0",
                           {layers: 'basic'} );
                 var google = new OpenLayers.Layer.Google( "Google Hybrid" , {type: G_HYBRID_MAP });
                 var ve = new OpenLayers.Layer.VirtualEarth( "VE");
@@ -53,8 +54,8 @@
             }
 
             function add() {
-                var url = 'http://boston.openguides.org/markers/AQUA.png';
-                var sz = new OpenLayers.Size(10, 17);
+                var url = 'http://www.openlayers.org/dev/img/marker.png';
+                var sz = new OpenLayers.Size(21, 25);
                 var calculateOffset = function(size) {
                                     return new OpenLayers.Pixel(-(size.w/2), -size.h);
                                  };
@@ -77,6 +78,7 @@
         <h1 id="title">Base Layers Example</h1>
 
         <div id="tags">
+            Google, Yahoo, Virtual Earth, Bing, MultiMap, cleanup
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/behavior-fixed-http-gml.html
===================================================================
--- sandbox/ahocevar/playground/examples/behavior-fixed-http-gml.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/behavior-fixed-http-gml.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,7 +10,7 @@
             function init(){
                 map = new OpenLayers.Map('map');
                 var wms = new OpenLayers.Layer.WMS(
-                    "OpenLayers WMS", "http://labs.metacarta.com/wms/vmap0",
+                    "OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'}
                 );
 
@@ -31,6 +31,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">Vector Behavior Example (Fixed/HTTP/GML)</h1>
+        <div id="tags">
+            vector, strategy, strategies, protocoll, advanced, gml, http, fixed
+        </div>
         <p id="shortdesc">
             Vector layer with a Fixed strategy, HTTP protocol, and GML format.
         </p>

Copied: sandbox/ahocevar/playground/examples/bing.html (from rev 10919, trunk/openlayers/examples/bing.html)
===================================================================
--- sandbox/ahocevar/playground/examples/bing.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/bing.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,51 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Bing Example</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <script src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&mkt=en-us"></script>
+
+    <script src="../lib/OpenLayers.js"></script>
+    <script>
+
+        var map;
+
+        function init(){
+            map = new OpenLayers.Map("map");
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+            var shaded = new OpenLayers.Layer.VirtualEarth("Shaded", {
+                type: VEMapStyle.Shaded
+            });
+            var hybrid = new OpenLayers.Layer.VirtualEarth("Hybrid", {
+                type: VEMapStyle.Hybrid
+            });
+            var aerial = new OpenLayers.Layer.VirtualEarth("Aerial", {
+                type: VEMapStyle.Aerial
+            });
+
+            map.addLayers([shaded, hybrid, aerial]);
+
+            map.setCenter(new OpenLayers.LonLat(-110, 45), 3);
+        }
+
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Bing Example</h1>
+
+    <div id="tags">
+        Bing, Microsoft, Virtual Earth
+    </div>
+
+    <p id="shortdesc">
+        Demonstrates the use of Bing layers.
+    </p>
+
+    <div id="map" class="smallmap"></div>
+    <div id="docs">This example demonstrates the ability to create layers using tiles from Bing maps.</div>
+  </body>
+</html>
+
+

Modified: sandbox/ahocevar/playground/examples/boxes-vector.html
===================================================================
--- sandbox/ahocevar/playground/examples/boxes-vector.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/boxes-vector.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,6 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
-        <title>OpenLayers Boxes Example</title>
+        <title>OpenLayers Boxes Vector Example</title>
         <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
         <link rel="stylesheet" href="style.css" type="text/css" />
         <script src="../lib/OpenLayers.js"></script>
@@ -16,7 +16,7 @@
                 map = new OpenLayers.Map('map');
 
                 var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'} );
 
                 var boxes  = new OpenLayers.Layer.Vector( "Boxes" );
     
@@ -38,9 +38,10 @@
         </script>
     </head>
     <body onload="init()">
-        <h1 id="title">Boxes Example</h1>
+        <h1 id="title">Boxes Example Vector</h1>
 
         <div id="tags">
+            box, vector, annotation
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/boxes.html
===================================================================
--- sandbox/ahocevar/playground/examples/boxes.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/boxes.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
                 map = new OpenLayers.Map('map');
 
                 var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'} );
 
                 var boxes  = new OpenLayers.Layer.Boxes( "Boxes" );
     
@@ -40,6 +40,7 @@
         <h1 id="title">Boxes Example</h1>
 
         <div id="tags">
+            box, annotation
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/browser-name.html
===================================================================
--- sandbox/ahocevar/playground/examples/browser-name.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/browser-name.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -47,7 +47,7 @@
             };
 
             var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'},
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'},
                 options);
 
             var options2 = {
@@ -75,9 +75,11 @@
   <body onload="init()">
     <h1 id="title" style="display:inline;">Example Showing Browser Name</h1>
     <h3 id="browserHeader" style="display:inline;"></h3>
+    
+    <div id="tags">
+        browser, vendor  
+    </div>
 
-    <div id="tags"></div>
-
     <p id="shortdesc">
         Demonstrate a simple map that shows the browser name.
     </p>

Modified: sandbox/ahocevar/playground/examples/buffer.html
===================================================================
--- sandbox/ahocevar/playground/examples/buffer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/buffer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,15 +13,15 @@
             function init(){
                 map = new OpenLayers.Map( 'map' );
                 layer = new OpenLayers.Layer.WMS( "0 buffer: OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0",
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0",
                         {layers: 'basic'}, {'buffer':0} );
                 map.addLayer(layer);
                 layer = new OpenLayers.Layer.WMS( "1 buffer: OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0",
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0",
                         {layers: 'basic'}, {'buffer':1} );
                 map.addLayer(layer);
                 layer = new OpenLayers.Layer.WMS( "4 buffer: OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0",
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0",
                         {layers: 'basic'}, {'buffer':4} );
                 map.addLayer(layer);
                 map.addControl(new OpenLayers.Control.LayerSwitcher())
@@ -33,6 +33,7 @@
         <h1 id="title">Buffer Example</h1>
 
         <div id="tags">
+            buffer, performance, tile
         </div>
 
         <p id="shortdesc">

Copied: sandbox/ahocevar/playground/examples/canvas.html (from rev 10919, trunk/openlayers/examples/canvas.html)
===================================================================
--- sandbox/ahocevar/playground/examples/canvas.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/canvas.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>Canvas Renderer Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
+        <script src="canvas.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Canvas Renderer Example</h1>
+        <div id="tags">
+            canvas, renderer, advanced,
+        </div>
+        <p id="shortdesc">
+            Demonstrates the use of the canvas renderer with a vector layer.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                This example shows a vector layer that uses the Canvas renderer
+                where available. The order of the renderers given in the layer
+                options is used to locate the first available renderer.
+            </p>
+            <p>
+                See the <a href="canvas.js" target="_blank">canvas.js source</a>
+                to see how this is done.
+            </p> 
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/canvas.js (from rev 10919, trunk/openlayers/examples/canvas.js)
===================================================================
--- sandbox/ahocevar/playground/examples/canvas.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/canvas.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,62 @@
+var map, layer, styleMap;
+OpenLayers.ProxyHost = "proxy.cgi?url=";
+
+function init() {
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: new OpenLayers.Projection("EPSG:900913"),
+        displayProjection: new OpenLayers.Projection("EPSG:4326"),
+        units: "m",
+        maxResolution: 156543.0339,
+        maxExtent: new OpenLayers.Bounds(
+            -20037508, -20037508, 20037508, 20037508
+        )
+    });
+
+    var g = new OpenLayers.Layer.Google("Google Layer", {
+        sphericalMercator: true
+    });
+    map.addLayers([g]);
+
+    // prepare to style the data
+    styleMap = new OpenLayers.StyleMap({
+        strokeColor: "black",
+        strokeWidth: 2,
+        strokeOpacity: 0.5,
+        fillOpacity: 0.2
+    });
+
+    // create a color table for state FIPS code
+    var colors = ["red", "orange", "yellow", "green", "blue", "purple"];
+    var code, fips = {};
+    for(var i=1; i<=66; ++i) {
+        code = "0" + i;
+        code = code.substring(code.length - 2);
+        fips[code] = {fillColor: colors[i % colors.length]};
+    }
+    // add unique value rules with your color lookup
+    styleMap.addUniqueValueRules("default", "STATE_FIPS", fips);
+    
+    // create a vector layer using the canvas renderer (where available)
+    var wfs = new OpenLayers.Layer.Vector("States", {
+        strategies: [new OpenLayers.Strategy.BBOX()],
+        protocol: new OpenLayers.Protocol.WFS({
+            version: "1.1.0",
+            srsName: "EPSG:900913",
+            url:  "http://demo.opengeo.org/geoserver/wfs",
+            featureType: "states",
+            featureNS: "http://www.openplans.org/topp"
+        }),
+        styleMap: styleMap,
+        renderers: ["Canvas", "SVG", "VML"]
+    });
+    map.addLayer(wfs);
+
+    // if you want to use Geographic coords, transform to ESPG:900913
+    var ddBounds = new OpenLayers.Bounds(
+        -73.839111,40.287907,-68.214111,44.441624
+    );
+    map.zoomToExtent(
+        ddBounds.transform(map.displayProjection, map.getProjectionObject())
+    );
+}

Modified: sandbox/ahocevar/playground/examples/click-handler.html
===================================================================
--- sandbox/ahocevar/playground/examples/click-handler.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/click-handler.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
             #east {
                 position: absolute;
                 left: 370px;
-                top: 3em;
+                top: 4em;
             }
 
             table td {
@@ -81,7 +81,7 @@
                 map = new OpenLayers.Map('map');
                 var layer = new OpenLayers.Layer.WMS(
                     "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'}
                 );
                 map.addLayers([layer]);
@@ -156,6 +156,7 @@
         <div id="west">
     
             <div id="tags">
+                event, events, propagation,  advanced
             </div>
     
             <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/click.html
===================================================================
--- sandbox/ahocevar/playground/examples/click.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/click.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -41,7 +41,7 @@
                 map = new OpenLayers.Map('map');
 
                 var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'} );
 
             var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
                 "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
@@ -65,17 +65,23 @@
         <h1 id="title">Click Event Example</h1>
 
         <div id="tags">
+            click control, double, doubleclick, double-click, event, events, 
+            propagation
         </div>
 
         <p id="shortdesc">
-            This example shows the use of the click handler and getLonLatFromViewPortPx functions to trigger events on mouse click. 
-
+            This example shows the use of the click handler and 
+            getLonLatFromViewPortPx functions to trigger events on mouse click. 
         </p>
 
         <div id="map" class="smallmap"></div>
     
         <div id="docs">
-            Using the Click handler allows you to (for example) catch clicks without catching double clicks, something that standard browser events don't do for you. (Try double clicking: you'll zoom in, whereas using the browser click event, you would just get two alerts.) This example click control shows you how to use it. 
+            Using the Click handler allows you to (for example) catch clicks 
+            without catching double clicks, something that standard browser 
+            events don't do for you. (Try double clicking: you'll zoom in, 
+            whereas using the browser click event, you would just get two 
+            alerts.) This example click control shows you how to use it. 
         </div>
     </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/controls.html
===================================================================
--- sandbox/ahocevar/playground/examples/controls.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/controls.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -26,7 +26,7 @@
     
 
                 var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
                 var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
                     "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
@@ -49,6 +49,7 @@
         <h1 id="title">Map Controls Example</h1>
 
         <div id="tags">
+            control, basic
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/custom-control-point.html
===================================================================
--- sandbox/ahocevar/playground/examples/custom-control-point.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/custom-control-point.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -14,7 +14,7 @@
             map = new OpenLayers.Map( $('map') );
 
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
 
             var control = new OpenLayers.Control();
             OpenLayers.Util.extend(control, {
@@ -42,6 +42,7 @@
       <h1 id="title">Custom Control Point Example</h1>
 
       <div id="tags">
+        control, point, cleanup
       </div>
 
       <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/custom-control.html
===================================================================
--- sandbox/ahocevar/playground/examples/custom-control.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/custom-control.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
             function init(){
                 map = new OpenLayers.Map('map');
                 layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
 
                 var control = new OpenLayers.Control();
                 OpenLayers.Util.extend(control, {
@@ -45,15 +45,20 @@
     <body onload="init()">
         <h1 id="title">Custom Control Example</h1>
 
-          <div id="tags">
+        <div id="tags">
+            control, panel, rectangle
         </div>
 
         <p id="shortdesc">
-            Demonstrate the addition of a draggable rectangle to the OpenLayers window.
+            Demonstrate the addition of a rectangle to the OpenLayers window.
         </p>
       
         <div id="map" class="smallmap"></div>
 
-        <div id="docs"></div>
+        <div id="docs">
+            The control allows you to draw a rectangle, that reports its coordinates
+            after creation. Hold down the shift key on your keyboard and draw a 
+            rectangle with the mouse.
+        </div>
     </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/custom-style.html
===================================================================
--- sandbox/ahocevar/playground/examples/custom-style.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/custom-style.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,7 +10,7 @@
             }
             div.olControlMousePosition {
                 font-family: Verdana;
-                font-size: 0.5em;
+                font-size: 2em;
                 color: red;
             }
         </style>
@@ -25,7 +25,7 @@
                 var options = {theme: null};
                 map = new OpenLayers.Map('map', options);
                 layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
 
                 map.addControl(new OpenLayers.Control.MousePosition());
                 map.addLayer(layer);
@@ -37,6 +37,7 @@
         <h1 id="title">Custom Style Example</h1>
 
         <div id="tags">
+            styling, css, stylesheet, theming, theme
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/debug.html
===================================================================
--- sandbox/ahocevar/playground/examples/debug.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/debug.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -27,7 +27,9 @@
     <body>
         <h1 id="title">Debug Example</h1>
 
-        <div id="tags"></div>
+        <div id="tags">
+            debugging, error, fix, fixing, console, firebug, developers, advanced
+        </div>
 
         <p id="shortdesc">
             Demonstrate console calls to a Firebug console. Requires Firefox. Mostly for developers.

Copied: sandbox/ahocevar/playground/examples/document-drag.html (from rev 10919, trunk/openlayers/examples/document-drag.html)
===================================================================
--- sandbox/ahocevar/playground/examples/document-drag.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/document-drag.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Document Drag Example</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, layer;
+        function init(){
+            map = new OpenLayers.Map( 'map', {controls: [
+                new OpenLayers.Control.Navigation({documentDrag: true}),
+                new OpenLayers.Control.PanZoom(),
+                new OpenLayers.Control.ArgParser(),
+                new OpenLayers.Control.Attribution()
+            ]} );
+            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
+                    {layers: 'basic'} );
+            map.addLayer(layer);
+            map.zoomToMaxExtent();
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">OpenLayers Document Drag Example</h1>
+
+    <div id="tags">
+        drag
+    </div>
+
+    <div id="shortdesc">Keep on dragging even when the mouse cursor moves outside of the map</div>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+        This example shows how to make a map draggable outside of the map itself.
+    </div>
+  </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/donut.html (from rev 10919, trunk/openlayers/examples/donut.html)
===================================================================
--- sandbox/ahocevar/playground/examples/donut.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/donut.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers Polygon Hole Digitizing</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <style>
+            #controlToggle li {
+                list-style: none;
+            }
+            .olControlAttribution {
+                font-size: 9px;
+                bottom: 2px;
+            }
+            #output {
+                margin: 1em;
+                font-size: 0.9em;
+            }
+        </style>
+    </head>
+    <body>
+        <h1 id="title">Drawing Holes in Polygons</h1>
+        <div id="tags">
+            draw polygon hole
+        </div>         
+        <p id="shortdesc">
+            The DrawFeature control can be used to digitize donut polygons.
+        </p>
+        
+        <div id="map" class="smallmap"></div>
+        <ul id="controlToggle">
+            <li>
+                <input type="radio" name="type" value="none" id="noneToggle"
+                       onclick="toggleControl(this);" checked="checked">
+                <label for="noneToggle">navigate</label>
+            </li>
+            <li>
+                <input type="radio" name="type" value="polygon" id="polygonToggle" onclick="toggleControl(this);">
+                <label for="polygonToggle">draw polygon</label>
+            </li>
+        </ul>
+        <div id="output"></div>
+        <div id="docs">
+            <p>
+                To digitize holes in polygons, hold down the <code>Alt</code> 
+                key and draw over an existing polygon.  By default, the 
+                <code>Shift</code> key triggers freehand drawing.  Use a 
+                combination of the <code>Shift</code> and <code>Alt</code> keys
+                to digitize holes in freehand mode.
+            </p>
+            <p>
+                See the <a href="donut.js" target="_blank">
+                donut.js source</a> for details on how this is done.
+            </p>
+        </div>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="donut.js"></script>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/donut.js (from rev 10919, trunk/openlayers/examples/donut.js)
===================================================================
--- sandbox/ahocevar/playground/examples/donut.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/donut.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,38 @@
+var map = new OpenLayers.Map({
+    div: "map",
+    layers: [
+        new OpenLayers.Layer.OSM(),
+        new OpenLayers.Layer.Vector()
+    ],
+    center: new OpenLayers.LonLat(0, 0),
+    zoom: 1
+});
+
+var draw = new OpenLayers.Control.DrawFeature(
+    map.layers[1],
+    OpenLayers.Handler.Polygon,
+    {handlerOptions: {holeModifier: "altKey"}}
+);
+map.addControl(draw);
+
+// optionally listen for sketch events on the layer
+var output = document.getElementById("output");
+function updateOutput(event) {
+    window.setTimeout(function() {
+        output.innerHTML = event.type + " " + event.feature.id;
+    }, 100);
+}
+map.layers[1].events.on({
+    sketchmodified: updateOutput,
+    sketchcomplete: updateOutput
+})
+
+// add behavior to UI elements
+function toggleControl(element) {
+    if (element.value === "polygon" && element.checked) {
+        draw.activate();
+    } else {
+        draw.deactivate();
+    }
+}
+document.getElementById("noneToggle").checked = true;
\ No newline at end of file

Modified: sandbox/ahocevar/playground/examples/doubleSetCenter.html
===================================================================
--- sandbox/ahocevar/playground/examples/doubleSetCenter.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/doubleSetCenter.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,9 @@
     <body>
         <h1 id="title">Double Set Center Example</h1>
 
-        <div id="tags"></div>
+        <div id="tags">
+            center, centering, cleanup
+        </div>
 
         <p id="shortdesc">
             Demonstrate the behavior of two calls to set the center after instatiating the layer object.
@@ -20,7 +22,7 @@
         <script defer="defer" type="text/javascript">
             var map = new OpenLayers.Map('map');
             var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(wms);
             map.setCenter(new OpenLayers.LonLat(100,10));
             map.setCenter(new OpenLayers.LonLat(1,1));

Modified: sandbox/ahocevar/playground/examples/drag-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/drag-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/drag-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,7 +21,7 @@
             function init(){
                 map = new OpenLayers.Map('map');
                 var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'});
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'});
     
                 vectors = new OpenLayers.Layer.Vector("Vector Layer");
 
@@ -62,7 +62,9 @@
     <body onload="init()">
         <h1 id="title">Drag Feature Example</h1>
 
-        <div id="tags"></div>
+        <div id="tags">
+            point, line, linestring, polygon, digitizing, geometry, draw, drag
+        </div>
 
         <p id="shortdesc">
             Demonstrates point, line and polygon creation and editing.

Modified: sandbox/ahocevar/playground/examples/draw-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/draw-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/draw-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,16 +11,20 @@
             p {
                 width: 512px;
             }
+
+            /* avoid pink tiles */
+            .olImageLoadError {
+                background-color: transparent !important;
+            }
         </style>
         <script src="../lib/OpenLayers.js"></script>
         <script type="text/javascript">
             var map, drawControls;
-            OpenLayers.Util.onImageLoadErrorColor = "transparent";
             function init(){
                 map = new OpenLayers.Map('map');
 
                 var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'});
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'});
 
                 var pointLayer = new OpenLayers.Layer.Vector("Point Layer");
                 var lineLayer = new OpenLayers.Layer.Vector("Line Layer");
@@ -63,7 +67,9 @@
     <body onload="init()">
         <h1 id="title">OpenLayers Draw Feature Example</h1>
 
-        <div id="tags"></div>
+        <div id="tags">
+            point, line, linestring, polygon, digitizing, geometry, draw, drag
+        </div>
 
         <p id="shortdesc">
             Demonstrate on-screen digitizing tools for point, line, and polygon creation.

Copied: sandbox/ahocevar/playground/examples/dynamic-text-layer.html (from rev 10919, trunk/openlayers/examples/dynamic-text-layer.html)
===================================================================
--- sandbox/ahocevar/playground/examples/dynamic-text-layer.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/dynamic-text-layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,93 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>OpenLayers Vector Behavior Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <script type="text/javascript">
+            var map;
+        
+            function init(){
+                map = new OpenLayers.Map('map');
+                var wms = new OpenLayers.Layer.WMS(
+                    "OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0",
+                    {layers: 'basic'}
+                );
+
+                var layer = new OpenLayers.Layer.Vector("POIs", {
+                    strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1.1})],
+                    protocol: new OpenLayers.Protocol.HTTP({
+                        url: "textfile.txt",
+                        format: new OpenLayers.Format.Text()
+                    })
+                });
+
+                map.addLayers([wms, layer]);
+                map.zoomToMaxExtent();
+
+                // Interaction; not needed for initial display.
+                selectControl = new OpenLayers.Control.SelectFeature(layer);
+                map.addControl(selectControl);
+                selectControl.activate();
+                layer.events.on({
+                    'featureselected': onFeatureSelect,
+                    'featureunselected': onFeatureUnselect
+                });
+            }
+             
+
+            // Needed only for interaction, not for the display.
+            function onPopupClose(evt) {
+                // 'this' is the popup.
+                selectControl.unselect(this.feature);
+            }
+            function onFeatureSelect(evt) {
+                feature = evt.feature;
+                popup = new OpenLayers.Popup.FramedCloud("featurePopup",
+                                         feature.geometry.getBounds().getCenterLonLat(),
+                                         new OpenLayers.Size(100,100),
+                                         "<h2>"+feature.attributes.title + "</h2>" +
+                                         feature.attributes.description,
+                                         null, true, onPopupClose);
+                feature.popup = popup;
+                popup.feature = feature;
+                map.addPopup(popup);
+            }
+            function onFeatureUnselect(evt) {
+                feature = evt.feature;
+                if (feature.popup) {
+                    popup.feature = null;
+                    map.removePopup(feature.popup);
+                    feature.popup.destroy();
+                    feature.popup = null;
+                }
+            }
+        </script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Dynamic POIs via a Text Layer</h1>
+        <div id="tags">
+            poi, dynamic data, text, format, strategy, popup, select, selection
+        </div>
+        <p id="shortdesc">
+           Loading dynamic data from a text file. 
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            The vector layer shown uses the BBOX strategy, the HTTP protocol,
+            and the Text format.
+            This setup appends "?bbox=west,south,east,north" to every
+            request. This allows you to configure the location as something
+            like 'textfile.php', and take the '?bbox=' parameter to select
+            data from a database or the like.
+<br /><br />
+            There is nothing about this example that limits it to text files;
+            you can do the same thing with KML, GeoJSON, etc.
+            <br /><br />
+            This is an alternative to something like the <a href="http://wiki.openstreetmap.org/index.php/OpenLayers_Dynamic_POI">OpenStreetMap "Dynamic POI"</a> example. The Layer is a standard vector layer, and interaction can be
+            configured via the SelectFeature control, as you can see in the 
+            latter half of the code, which allows you to open a popup when
+            a feature is selected.
+        </div>
+    </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/editingtoolbar-outside.html
===================================================================
--- sandbox/ahocevar/playground/examples/editingtoolbar-outside.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/editingtoolbar-outside.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -24,7 +24,7 @@
             map = new OpenLayers.Map('map', {theme: null});
             layer = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: "basic"}
             );
             map.addLayer(layer);
@@ -43,6 +43,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers EditingToolbar Outside Viewport</h1>
+    <div id="tags">
+        digitizing, point, line, linestring, polygon, editing, positioning, style
+    </div>
     <p id="shortdesc">
         Display an editing toolbar panel outside the map viewport.
     </p>

Modified: sandbox/ahocevar/playground/examples/editingtoolbar.html
===================================================================
--- sandbox/ahocevar/playground/examples/editingtoolbar.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/editingtoolbar.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -15,7 +15,7 @@
 
             function init(){
                 layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
     
                 vlayer = new OpenLayers.Layer.Vector( "Editable" );
                 map = new OpenLayers.Map( 'map', {
@@ -33,7 +33,9 @@
     <body onload="init()">
         <h1 id="title">Editing Toolbar Example</h1>
 
-        <div id="tags"></div>
+        <div id="tags">
+            digitizing, point, line, linestring, polygon, editing
+        </div>
 
         <p id="shortdesc">
             Demonstrate polygon, polyline and point creation and editing tools.

Modified: sandbox/ahocevar/playground/examples/events.html
===================================================================
--- sandbox/ahocevar/playground/examples/events.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/events.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -18,7 +18,7 @@
             #output {
                 position: absolute;
                 left: 550px;
-                top: 40px;
+                top: 4em;
                 width: 350px;
                 height: 400px;
             }
@@ -106,7 +106,7 @@
                 
                 var vmap = new OpenLayers.Layer.WMS(
                     "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'}
                 );
                 var landsat = new OpenLayers.Layer.WMS(
@@ -136,6 +136,7 @@
         <h1 id="title">Event Handling</h1>
 
         <div id="tags">
+            event, events, handler, listener, cleanup
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/example-list.html
===================================================================
--- sandbox/ahocevar/playground/examples/example-list.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/example-list.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -34,6 +34,12 @@
                 font-weight: bold;
                 color: #333;
             }
+            .ex_tags{
+                display: inline;
+                font-size: smaller;
+                font-style: italic;
+                color: #333;
+            }
             .ex_filename {
                 font-weight: normal;
                 font-size: 0.8em;
@@ -92,8 +98,6 @@
         <script type="text/javascript" src="Jugl.js"></script>
         <script type="text/javascript" src="example-list.js"></script>
         <script type="text/javascript">
-            // import
-            var Jugl = window["http://jugl.tschaub.net/trunk/lib/Jugl.js"];
             var template, target;
 
             function listExamples(examples) {
@@ -195,7 +199,7 @@
                 }
             }
             window.onload = function() {
-                template = new Jugl.Template("template");
+                template = new jugl.Template("template");
                 target = document.getElementById("examples");
                 listExamples(info.examples);
                 document.getElementById("exwin").src = "../examples/example.html";
@@ -231,6 +235,9 @@
                         <p class="ex_classes" jugl:content="example.classes">
                             Related Classes go here
                         </p>
+                        <div class="ex_tags" jugl:content="'...tagged with ' + example.tags">
+                            
+                        </div>
                     </a>
                 </li>
             </ul>

Modified: sandbox/ahocevar/playground/examples/example.html
===================================================================
--- sandbox/ahocevar/playground/examples/example.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/example.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,56 +1,22 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>OpenLayers Example</title>
-    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
-    <link rel="stylesheet" href="style.css" type="text/css" />
-    <script src="../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        // making this a global variable so that it is accessible for
-        // debugging/inspecting in Firebug
-        var map = null;
-
-        function init(){
-
-            map = new OpenLayers.Map('map');
-
-            var ol_wms = new OpenLayers.Layer.WMS(
-                "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
-                {layers: 'basic'}
-            );
-
-            var jpl_wms = new OpenLayers.Layer.WMS(
-                "NASA Global Mosaic",
-                "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
-                {layers: "landsat7"}
-            );
-
-            var dm_wms = new OpenLayers.Layer.WMS(
-                "DM Solutions Demo",
-                "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap",
-                {
-                    layers: "bathymetry,land_fn,park,drain_fn,drainage," +
-                            "prov_bound,fedlimit,rail,road,popplace",
-                    transparent: "true", format: "image/png"},
-                {
-                    minResolution: 0.17578125,
-                    maxResolution: 0.703125
-                }
-            );
-
-            map.addLayers([ol_wms, jpl_wms, dm_wms]);
-            map.addControl(new OpenLayers.Control.LayerSwitcher());
-            map.zoomToMaxExtent();
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">OpenLayers Example</h1>
-    <div id="tags"></div>
-    <p id="shortdesc">
-        Demonstrate a simple map with an overlay that includes layer switching controls.
-    </p>
-    <div id="map" class="smallmap"></div>
-    <div id="docs"></div>
-  </body>
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+    </head>
+    <body>
+        <h1 id="title">OpenLayers Example</h1>
+        <div id="tags">simple, basic</div>
+        <p id="shortdesc">
+            Demonstrate a simple map with an overlay that includes layer switching controls.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>This is a basic example demonstrating the use of a map with two layers and a few controls.</p>
+            <p>View the <a href="example.js" target="_blank">example.js</a> source to see how this is done.</p>
+        </div>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="example.js"></script>
+    </body>
 </html>

Copied: sandbox/ahocevar/playground/examples/example.js (from rev 10919, trunk/openlayers/examples/example.js)
===================================================================
--- sandbox/ahocevar/playground/examples/example.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/example.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,23 @@
+var map = new OpenLayers.Map("map");
+
+var ol_wms = new OpenLayers.Layer.WMS(
+    "OpenLayers WMS",
+    "http://vmap0.tiles.osgeo.org/wms/vmap0",
+    {layers: "basic"}
+);
+
+var dm_wms = new OpenLayers.Layer.WMS(
+    "Canadian Data",
+    "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap",
+    {
+        layers: "bathymetry,land_fn,park,drain_fn,drainage," +
+                "prov_bound,fedlimit,rail,road,popplace",
+        transparent: "true",
+        format: "image/png"
+    },
+    {isBaseLayer: false, visibility: false}
+);
+
+map.addLayers([ol_wms, dm_wms]);
+map.addControl(new OpenLayers.Control.LayerSwitcher());
+map.zoomToMaxExtent();

Copied: sandbox/ahocevar/playground/examples/filter-strategy.html (from rev 10919, trunk/openlayers/examples/filter-strategy.html)
===================================================================
--- sandbox/ahocevar/playground/examples/filter-strategy.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/filter-strategy.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers Filter Strategy Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="../lib/OpenLayers.js"></script>
+        <script>OpenLayers.ImgPath = "../img/";</script>
+        <style>
+            .olControlAttribution {
+                font-size: 9px;
+                bottom: 2px;
+            }
+        </style>
+    </head>
+    <body>
+        <h1 id="title">Filter Strategy</h1>
+        <div id="tags">
+            filter, strategy, strategies, kml, advanced
+        </div>
+        <p id="shortdesc">
+            Demonstrates the filter strategy for limiting features passed to the layer.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <label for="span">time span (seconds)</label>
+        <select id="span" name="span">
+            <option value="15">15</option>
+            <option value="30">30</option>
+            <option value="60" selected>60</option>
+            <option value="120">120</option>
+            <option value="240">240</option>
+        </select>
+        <input type="button" id="start" value="start">
+        <input type="button" id="stop" value="stop"><br><br>
+        <div id="docs">
+            <p>
+                This example uses a filter strategy to limit the features that are passed
+                to a layer.  Features bound for this layer have a <code>when</code> attribute
+                with date values.  A filter strategy is constructed with a between filter
+                that limits the span of dates shown.  A simple animation cycles through
+                the domain of the <code>when</code> values, calling <code>setFilter</code>
+                on the strategy with an updated filter.
+            </p><p>
+                View the <a href="filter-strategy.js" target="_blank">filter-strategy.js</a>
+                source to see how this is done
+            </p>
+        </div>
+        <script src="filter-strategy.js"></script>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/filter-strategy.js (from rev 10919, trunk/openlayers/examples/filter-strategy.js)
===================================================================
--- sandbox/ahocevar/playground/examples/filter-strategy.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/filter-strategy.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,84 @@
+var map, filter, filterStrategy;
+var animationTimer;
+var currentDate;
+var startDate = new Date(1272736800000); // lower bound of when values
+var endDate = new Date(1272737100000); // upper value of when values
+var step = 8; // sencods to advance each interval
+var interval = 0.125; // seconds between each step in the animation
+
+function startAnimation() {
+    if (animationTimer) {
+        stopAnimation(true);
+    }
+    if (!currentDate) {
+        currentDate = startDate;
+    }
+    var spanEl = document.getElementById("span");
+    var next = function() {
+        var span = parseInt(spanEl.value, 10);
+        if (currentDate < endDate) {
+            filter.lowerBoundary = currentDate;
+            filter.upperBoundary = new Date(currentDate.getTime() + (span * 1000));
+            filterStrategy.setFilter(filter);
+            currentDate = new Date(currentDate.getTime() + (step * 1000))
+        } else {
+            stopAnimation(true);
+        }
+    }
+    animationTimer = window.setInterval(next, interval * 1000);
+}
+
+function stopAnimation(reset) {
+    window.clearInterval(animationTimer);
+    animationTimer = null;
+    if (reset === true) {
+        currentDate = null;
+    }
+}
+
+// add behavior to elements
+document.getElementById("start").onclick = startAnimation;
+document.getElementById("stop").onclick = stopAnimation;
+var spanEl = document.getElementById("span");
+
+var mercator = new OpenLayers.Projection("EPSG:900913");
+var geographic = new OpenLayers.Projection("EPSG:4326");
+map = new OpenLayers.Map("map");
+
+var osm = new OpenLayers.Layer.OSM();
+
+filter = new OpenLayers.Filter.Comparison({
+    type: OpenLayers.Filter.Comparison.BETWEEN,
+    property: "when",
+    lowerBoundary: startDate,
+    upperBoundary: new Date(startDate.getTime() + (parseInt(spanEl.value, 10) * 1000))
+});
+
+filterStrategy = new OpenLayers.Strategy.Filter({filter: filter});
+
+var flights = new OpenLayers.Layer.Vector("Aircraft Locations", {
+    projection: geographic,
+    strategies: [new OpenLayers.Strategy.Fixed(), filterStrategy],
+    protocol: new OpenLayers.Protocol.HTTP({
+        url: "kml-track.kml",
+        format: new OpenLayers.Format.KML({
+            extractTracks: true
+            //,extractStyles: true // use style from KML instead of styleMap below
+        })
+    }),
+    styleMap: new OpenLayers.StyleMap({
+        "default": new OpenLayers.Style({
+            graphicName: "circle",
+            pointRadius: 3,
+            fillOpacity: 0.25,
+            fillColor: "#ffcc66",
+            strokeColor: "#ff9933",
+            strokeWidth: 1
+        })
+    }),
+    renderers: ["Canvas", "SVG", "VML"]
+});
+
+map.addLayers([osm, flights]);
+map.setCenter(new OpenLayers.LonLat(-93.2735, 44.8349).transform(geographic, mercator), 8);
+

Modified: sandbox/ahocevar/playground/examples/filter.html
===================================================================
--- sandbox/ahocevar/playground/examples/filter.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/filter.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -63,6 +63,10 @@
   </head>
   <body>
     <h1 id="title">Filter Encoding</h1>
+    <div id="tags">
+        filter, format, comparison, filter encoding, fe, logical, attribute,
+        attributive, spatial, advanced
+    </div>
     <p id="shortdesc">
         Using the filter format write out filter objects.
     </p>

Modified: sandbox/ahocevar/playground/examples/fractional-zoom.html
===================================================================
--- sandbox/ahocevar/playground/examples/fractional-zoom.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/fractional-zoom.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
                   numZoomLevels: 10 });
             var wms = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             );
             map.addLayers([wms]);
@@ -40,6 +40,7 @@
     <h1 id="title">Fractional Zoom Example</h1>
 
     <div id="tags">
+        zoomlevel, unlimited zoom, scale
     </div>
     <p id="shortdesc">
             Shows the use of a map with fractional (or non-discrete) zoom levels.

Modified: sandbox/ahocevar/playground/examples/fullScreen.html
===================================================================
--- sandbox/ahocevar/playground/examples/fullScreen.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/fullScreen.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -17,6 +17,9 @@
                 bottom: 1em;
                 left: 1em;
                 width: 512px;
+                z-index: 20000;
+                background-color: white;
+                padding: 0 0.5em 0.5em 0.5em;
             }
         </style>
         <script src="../lib/OpenLayers.js"></script>
@@ -26,7 +29,7 @@
                 map = new OpenLayers.Map('map');
 
             var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
             var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
                 "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
@@ -40,8 +43,8 @@
 
                 map.addLayers([ol_wms, jpl_wms, dm_wms]);
                 map.addControl(new OpenLayers.Control.LayerSwitcher());
-                // map.setCenter(new OpenLayers.LonLat(0, 0), 0);
-                map.zoomToMaxExtent();
+                map.setCenter(new OpenLayers.LonLat(0, 0), 6);
+                //map.zoomToMaxExtent();
             }
         </script>
     </head>
@@ -51,7 +54,9 @@
           <div id="text">
               <h1 id="title">Full Screen Example</h1>
 
-              <div id="tags"></div>
+              <div id="tags">
+                css, style, fullscreen, window, margin, padding, scrollbar
+              </div>
 
               <p id="shortdesc">
                 Demonstrate a map that fill the entire browser window.

Modified: sandbox/ahocevar/playground/examples/geojson.html
===================================================================
--- sandbox/ahocevar/playground/examples/geojson.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/geojson.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,7 +12,7 @@
         function init(){
             map = new OpenLayers.Map( 'map' );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
@@ -57,6 +57,17 @@
   </head>
   <body onload="init()">
     <h1 id="title">GeoJSON Example</h1>
+    
+    <div id="tags">
+       JSON, GeoJSON
+    </div>
+
+      <p id="shortdesc">
+        Demonstrate the use of the GeoJSON format.
+    </p>
     <div id="map" class="smallmap"></div>
+    <div id="docs">
+        This example uses the GeoJSON format.
+    </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/georss-flickr.html
===================================================================
--- sandbox/ahocevar/playground/examples/georss-flickr.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/georss-flickr.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
@@ -94,7 +94,23 @@
   </head>
   <body onload="init()">
     <h1 id="title">GeoRSS from Flickr in OpenLayers</h1>
-    <p>The displayed GeoRSS feed has a <tt>&lt;media:thumbnail/&gt;</tt> property for each item. An extended <tt>createFeatureFromItem()</tt> function is used to add this attribute to the attributes hash of each feature read in by <tt>OpenLayers.Format.GeoRSS</tt>. The example is configured with a style to render each item with its thumbnail image. Also, to show how rules work, we defined a rule that if the title of an rss item contains "powder", it will be rendered larger than the others.</p>
+    <div id="tags">
+        georss, style, styling, marker, flickr, thumbnail, image, rule
+    </div>
+
+    <p id="shortdesc">
+        Display a flickr-feed on top of the map
+    </p>
+    
     <div id="map" class="smallmap"></div>
+    <div id="docs">
+    <p>The displayed GeoRSS feed has a <tt>&lt;media:thumbnail/&gt;</tt> 
+    property for each item. An extended <tt>createFeatureFromItem()</tt> 
+    function is used to add this attribute to the attributes hash of each 
+    feature read in by <tt>OpenLayers.Format.GeoRSS</tt>. The example is 
+    configured with a style to render each item with its thumbnail image. 
+    Also, to show how rules work, we defined a rule that if the title of an 
+    rss item contains "powder", it will be rendered larger than the others.</p>
+    </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/georss-markers.html
===================================================================
--- sandbox/ahocevar/playground/examples/georss-markers.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/georss-markers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,13 +11,13 @@
         function init(){
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
             var newl = new OpenLayers.Layer.GeoRSS( 'GeoRSS', 'georss.xml');
             map.addLayer(newl);
-            var yelp = new OpenLayers.Icon("http://openlayers.org/~crschmidt/yelp.png", new OpenLayers.Size(20,29));
+            var yelp = new OpenLayers.Icon("http://www.openlayers.org/images/OpenLayers.trac.png", new OpenLayers.Size(49,44));
             var newl = new OpenLayers.Layer.GeoRSS( 'Yelp GeoRSS', 'yelp-georss.xml', {'icon':yelp});
             map.addLayer(newl);
         }
@@ -26,7 +26,9 @@
   <body onload="init()">
     <h1 id="title">GeoRSS Marker Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        georss, style, styling, marker, flickr, image
+    </div>
 
     <p id="shortdesc">
         Demonstrate loading a GeoRSS feed using the GeoRSS parser.

Modified: sandbox/ahocevar/playground/examples/georss.html
===================================================================
--- sandbox/ahocevar/playground/examples/georss.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/georss.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
         function init(){
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
@@ -29,7 +29,9 @@
   <body onload="init()">
     <h1 id="title">GeoRSS Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        georss, style, styling, marker
+    </div>
 
     <p id="shortdesc">
         Display a couple of locally cached georss feeds on an a basemap.
@@ -48,9 +50,9 @@
                <input type="submit" onclick="addUrl(); return false;" value="Load Feed" onsubmit="addUrl(); return false;" />
         </form>
 
-        <p>The above input box allows the input of a URL to a GeoRSS feed. This feed can be local to the HTML page --
+        <p>The above input box allows the input of a URL to a GeoRSS feed. This feed can be local to the HTML page &mdash;
         for example, entering 'georss.xml' will work by default, because there is a local file in the directory called
-        georss.xml -- or, with a properly set up ProxyHost variable (as is used here), it will be able to load any
+        georss.xml &mdash; or, with a properly set up ProxyHost variable (as is used here), it will be able to load any
         HTTP URL which contains GeoRSS and display it. Anything else will simply have no effect.</p>
     </div>
   </body>

Modified: sandbox/ahocevar/playground/examples/getfeature-wfs.html
===================================================================
--- sandbox/ahocevar/playground/examples/getfeature-wfs.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/getfeature-wfs.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -18,8 +18,8 @@
             });
             layer = new OpenLayers.Layer.WMS(
                 "States WMS/WFS",
-                "http://demo.opengeo.org/geoserver/ows",
-                {layers: 'topp:states', format: 'image/gif'}
+                "http://v2.suite.opengeo.org/geoserver/ows",
+                {layers: 'usa:states', format: 'image/gif'}
             );
             select = new OpenLayers.Layer.Vector("Selection", {styleMap: 
                 new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"])
@@ -57,21 +57,25 @@
 <h1 id="title">WFS GetFeature Example (GeoServer)</h1>
 
 <div id="tags">
+WFS, GetFeature
 </div>
 
 <p id="shortdesc">
-    Shows how to use the GetFeature control to select features from a
-    WMS layer.  Click or drag a box to select features, use the Shift key to
-    add features to the selection, use the Ctrl key to toggle a feature's
-    selected status.  Note that this control also has a hover option, which is
-    enabled in this example.  This gives you a visual feedback by loading the
-    feature underneath the mouse pointer from the WFS, but causes a lot of
-    GetFeature requests to be issued.
+    Shows how to use the GetFeature control to select features from a WMS layer.
 </p>
 
 <div id="map" class="smallmap"></div>
 
-<div id="docs"></div>
+<div id="docs">
+    <p>
+        Click or drag a box to select features, use the Shift key to add
+        features to the selection, use the Ctrl key to toggle a feature's
+        selected status. Note that this control also has a hover option, which
+        is enabled in this example. This gives you a visual feedback by loading
+        the feature underneath the mouse pointer from the WFS, but causes a lot
+        of GetFeature requests to be issued.
+    </p>
+</div>
   </body>
 </html>
 

Modified: sandbox/ahocevar/playground/examples/getfeatureinfo-control.html
===================================================================
--- sandbox/ahocevar/playground/examples/getfeatureinfo-control.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/getfeatureinfo-control.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -37,7 +37,6 @@
             text-align:left;
             font-size:100%;
             font-weight:bold;
-            text-transform:uppercase;
             padding:.2em .2em;
 	}
 
@@ -161,7 +160,9 @@
   <body onload="load()">
       <h1 id="title">Feature Info Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        WMS, GetFeatureInfo
+      </div>
 
       <p id="shortdesc">
         Demonstrates the WMSGetFeatureInfo control for fetching information about a position from WMS (via GetFeatureInfo request).

Copied: sandbox/ahocevar/playground/examples/getfeatureinfo-popup.html (from rev 10919, trunk/openlayers/examples/getfeatureinfo-popup.html)
===================================================================
--- sandbox/ahocevar/playground/examples/getfeatureinfo-popup.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/getfeatureinfo-popup.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,92 @@
+<html>
+  <head>
+    <title>GetFeatureInfo Popup</title>
+    <script src="../lib/OpenLayers.js"></script>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script>
+    OpenLayers.ProxyHost = "proxy.cgi?url=";
+    
+    var map, info;
+    
+    function load() {
+        map = new OpenLayers.Map({
+            div: "map",
+            maxExtent: new OpenLayers.Bounds(143.834,-43.648,148.479,-39.573)
+        });
+
+        var political = new OpenLayers.Layer.WMS("State Boundaries",
+            "http://demo.opengeo.org/geoserver/wms", 
+            {'layers': 'topp:tasmania_state_boundaries', transparent: true, format: 'image/gif'},
+            {isBaseLayer: true}
+        );
+
+        var roads = new OpenLayers.Layer.WMS("Roads",
+            "http://demo.opengeo.org/geoserver/wms", 
+            {'layers': 'topp:tasmania_roads', transparent: true, format: 'image/gif'},
+            {isBaseLayer: false}
+        );
+
+        var cities = new OpenLayers.Layer.WMS("Cities",
+            "http://demo.opengeo.org/geoserver/wms", 
+            {'layers': 'topp:tasmania_cities', transparent: true, format: 'image/gif'},
+            {isBaseLayer: false}
+        );
+
+        var water = new OpenLayers.Layer.WMS("Bodies of Water",
+            "http://demo.opengeo.org/geoserver/wms", 
+            {'layers': 'topp:tasmania_water_bodies', transparent: true, format: 'image/gif'},
+            {isBaseLayer: false}
+        );
+
+        var highlight = new OpenLayers.Layer.Vector("Highlighted Features", {
+            displayInLayerSwitcher: false, 
+            isBaseLayer: false 
+        });
+        
+        map.addLayers([political, roads, cities, water, highlight]); 
+
+        info = new OpenLayers.Control.WMSGetFeatureInfo({
+            url: 'http://demo.opengeo.org/geoserver/wms', 
+            title: 'Identify features by clicking',
+            queryVisible: true,
+            eventListeners: {
+                getfeatureinfo: function(event) {
+                    map.addPopup(new OpenLayers.Popup.FramedCloud(
+                        "chicken", 
+                        map.getLonLatFromPixel(event.xy),
+                        null,
+                        event.text,
+                        null,
+                        true
+                    ));
+                }
+            }
+        });
+        map.addControl(info);
+        info.activate();
+
+        map.addControl(new OpenLayers.Control.LayerSwitcher());
+        map.zoomToMaxExtent();
+    }
+
+  </script>
+  </head>
+  <body onload="load()">
+      <h1 id="title">Feature Info in Popup</h1>
+
+      <div id="tags">
+        WMS, GetFeatureInfo, popup
+      </div>
+
+      <p id="shortdesc">
+        Demonstrates the WMSGetFeatureInfo control for fetching information
+        about a position from WMS (via GetFeatureInfo request).  Results
+        are displayed in a popup.
+      </p>
+
+      <div id="map" class="smallmap"></div>
+
+    <div id="docs"></div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/getfeatureinfo.html
===================================================================
--- sandbox/ahocevar/playground/examples/getfeatureinfo.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/getfeatureinfo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,9 @@
   <body>
       <h1 id="title">Feature Info Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        WMS, GetFeatureInfo, cleanup
+      </div>
 
       <p id="shortdesc">
         Demonstrates sending a GetFeatureInfo query to an OWS. Returns information about a map feature in the side DIV.
@@ -31,6 +33,7 @@
     OpenLayers.ProxyHost = "/dev/examples/proxy.cgi?url=";
     var map = new OpenLayers.Map('map', {'maxResolution':'auto'});
 
+// cleanup: this WMS is broken
     var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
         "http://world.freemap.in/cgi-bin/mapserv?map=/www/freemap.in/world/map/factbook.map", {'layers': 'factbook'} );
     map.addLayer(wms);

Modified: sandbox/ahocevar/playground/examples/gml-layer.html
===================================================================
--- sandbox/ahocevar/playground/examples/gml-layer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/gml-layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             map.zoomToExtent(new OpenLayers.Bounds(-3.922119,44.335327,4.866943,49.553833));
             map.addLayer(new OpenLayers.Layer.GML("GML", "gml/polygon.xml"));
@@ -23,7 +23,9 @@
   <body onload="init()">
       <h1 id="title">GML Layer Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        GML
+      </div>
 
       <p id="shortdesc">
           Loads locally stored GML vector data on a basemap. Includes GML example file.

Modified: sandbox/ahocevar/playground/examples/google-reproject.html
===================================================================
--- sandbox/ahocevar/playground/examples/google-reproject.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/google-reproject.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -37,7 +37,9 @@
   <body onload="init()">
     <h1 id="title">Google with Overlay Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        Google, overlay, mercator, reproject, cleanup
+    </div>
 
     <p id="shortdesc">
         Demonstrate a Google basemap used with boundary overlay layer.

Copied: sandbox/ahocevar/playground/examples/google-v3-alloverlays.html (from rev 10919, trunk/openlayers/examples/google-v3-alloverlays.html)
===================================================================
--- sandbox/ahocevar/playground/examples/google-v3-alloverlays.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/google-v3-alloverlays.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers Google (v3) Layer Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="google-v3-alloverlays.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Google (v3) allOverlays Layer Example</h1>
+        <div id="tags">
+            Google, overlay
+        </div>
+        <p id="shortdesc">
+            Demonstrate use the Google Maps v3 API with allOverlays set to true on the map.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                You can also use Google layers as overlays, e.g. in a map with
+                allOverlays set to true. Note some of the layers disappear as
+                you zoom in to levels that are not supported by all layers.  See the 
+                <a href="google-v3-alloverlays.js" target="_blank">google-v3-alloverlays.js source</a> 
+                to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/google-v3-alloverlays.js (from rev 10919, trunk/openlayers/examples/google-v3-alloverlays.js)
===================================================================
--- sandbox/ahocevar/playground/examples/google-v3-alloverlays.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/google-v3-alloverlays.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,35 @@
+var map;
+
+function init() {
+    map = new OpenLayers.Map('map', {allOverlays: true});
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    
+    // the SATELLITE layer has all 22 zoom level, so we add it first to
+    // become the internal base layer that determines the zoom levels of the
+    // map.
+    var gsat = new OpenLayers.Layer.Google(
+        "Google Satellite",
+        {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22}
+    );
+    var gphy = new OpenLayers.Layer.Google(
+        "Google Physical",
+        {type: google.maps.MapTypeId.TERRAIN, visibility: false}
+    );
+    var gmap = new OpenLayers.Layer.Google(
+        "Google Streets", // the default
+        {numZoomLevels: 20, visibility: false}
+    );
+    var ghyb = new OpenLayers.Layer.Google(
+        "Google Hybrid",
+        {type: google.maps.MapTypeId.HYBRID, numZoomLevels: 22, visibility: false}
+    );
+
+    map.addLayers([gsat, gphy, gmap, ghyb]);
+
+    // Google.v3 uses EPSG:900913 as projection, so we have to
+    // transform our coordinates
+    map.setCenter(new OpenLayers.LonLat(10.2, 48.9).transform(
+        new OpenLayers.Projection("EPSG:4326"),
+        map.getProjectionObject()
+    ), 5);
+}

Copied: sandbox/ahocevar/playground/examples/google-v3.html (from rev 10919, trunk/openlayers/examples/google-v3.html)
===================================================================
--- sandbox/ahocevar/playground/examples/google-v3.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/google-v3.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers Google (v3) Layer Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="google-v3.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Google (v3) Layer Example</h1>
+        <div id="tags">
+            Google, api key, apikey
+        </div>
+        <p id="shortdesc">
+            Demonstrate use the Google Maps v3 API.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                If you use the Google Maps v3 API with a Google layer, you don't
+                need to include an API key.  This layer only works in the 
+                spherical mercator projection.  See the 
+                <a href="google-v3.js" target="_blank">google-v3.js source</a> 
+                to see how this is done.
+            <p>
+                In order to position the Google attribution div in the default 
+                location, you must include the extra theme/default/google.css 
+                stylesheet.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/google-v3.js (from rev 10919, trunk/openlayers/examples/google-v3.js)
===================================================================
--- sandbox/ahocevar/playground/examples/google-v3.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/google-v3.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,32 @@
+var map;
+
+function init() {
+    map = new OpenLayers.Map('map');
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    
+    var gphy = new OpenLayers.Layer.Google(
+        "Google Physical",
+        {type: google.maps.MapTypeId.TERRAIN}
+    );
+    var gmap = new OpenLayers.Layer.Google(
+        "Google Streets", // the default
+        {numZoomLevels: 20}
+    );
+    var ghyb = new OpenLayers.Layer.Google(
+        "Google Hybrid",
+        {type: google.maps.MapTypeId.HYBRID, numZoomLevels: 20}
+    );
+    var gsat = new OpenLayers.Layer.Google(
+        "Google Satellite",
+        {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22}
+    );
+
+    map.addLayers([gphy, gmap, ghyb, gsat]);
+
+    // Google.v3 uses EPSG:900913 as projection, so we have to
+    // transform our coordinates
+    map.setCenter(new OpenLayers.LonLat(10.2, 48.9).transform(
+        new OpenLayers.Projection("EPSG:4326"),
+        map.getProjectionObject()
+    ), 5);
+}

Modified: sandbox/ahocevar/playground/examples/google.html
===================================================================
--- sandbox/ahocevar/playground/examples/google.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/google.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -28,7 +28,7 @@
             );
             var gsat = new OpenLayers.Layer.Google(
                 "Google Satellite",
-                {type: G_SATELLITE_MAP, numZoomLevels: 20}
+                {type: G_SATELLITE_MAP, numZoomLevels: 22}
             );
 
 
@@ -41,7 +41,9 @@
   <body onload="init()">
     <h1 id="title">Google Layer Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        Google
+    </div>
 
     <p id="shortdesc">
         Demonstrate use of the various types of Google layers.
@@ -56,7 +58,7 @@
         it is best to simply set your application to use the string "v=2" in
         the request, rather than tying your application to an explicit version.</p>
      <p>
-       In order to position the Google attribution div in the default ocation,
+       In order to position the Google attribution div in the default location,
        you must include the extra theme/default/google.css stylesheet.</p>
     </div>
   </body>

Modified: sandbox/ahocevar/playground/examples/graphic-name.html
===================================================================
--- sandbox/ahocevar/playground/examples/graphic-name.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/graphic-name.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -8,7 +8,7 @@
         // user custom graphicname
         
         OpenLayers.Renderer.symbol.lightning = [0,0, 4,2, 6,0, 10,5, 6,3, 4,5, 0,0];
-        OpenLayers.Renderer.symbol.rectangle = [0,0, 10,0, 10,4, 0,4, 0,0];
+        OpenLayers.Renderer.symbol.rectangle = [0,0, 4,0, 4,10, 0,10, 0,0];
             
         var map;
 
@@ -48,7 +48,8 @@
                 },
                 "select": {
                     pointRadius: 20,
-                    fillOpacity: 1
+                    fillOpacity: 1,
+                    rotation: 45
                 }
             });
 
@@ -71,7 +72,9 @@
   <body onload="init()">
     <h1 id="title">Named Graphics Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        vector, named graphic, star, cross, x, square, triangle, circle, style
+    </div>
 
     <p id="shortdesc">
         Shows how to use well-known graphic names.

Copied: sandbox/ahocevar/playground/examples/graticule.html (from rev 10919, trunk/openlayers/examples/graticule.html)
===================================================================
--- sandbox/ahocevar/playground/examples/graticule.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/graticule.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,112 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>OpenLayers Graticule Example</title>
+
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <style type="text/css">
+            #map {
+                width: 600px;
+                height: 300px;
+                border: 1px solid black;
+                float:left;
+            }
+            #map2 {
+                width: 400px;
+                height: 400px;
+                border: 1px solid black;
+                float:left;
+            }
+        </style>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="http://proj4js.org/lib/proj4js-compressed.js"></script>
+        <script type="text/javascript">
+            Proj4js.defs["EPSG:42304"]="+title=Atlas of Canada, LCC +proj=lcc +lat_1=49 +lat_2=77 +lat_0=49 +lon_0=-95 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs";
+            
+            var graticuleCtl1, graticuleCtl2;
+            var map1, map2;
+            function init(){
+              initLonLat();
+              initProjected();
+            }
+            function initLonLat(){
+                graticuleCtl1 = new OpenLayers.Control.Graticule({
+                    numPoints: 2, 
+                    labelled: true
+                });
+                map1 = new OpenLayers.Map('map', {
+                    controls: [
+                      graticuleCtl1,
+                      new OpenLayers.Control.LayerSwitcher(),
+                      new OpenLayers.Control.PanZoomBar(),
+                      new OpenLayers.Control.Navigation()
+                      ]
+                });
+
+                var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
+                    {layers: 'basic'}, {wrapDateLine: true} );
+
+                map1.addLayers([ol_wms]);
+                if (!map1.getCenter()) map1.zoomToMaxExtent();
+            };
+            
+            function initProjected(){
+                var extent = new OpenLayers.Bounds(-2200000,-712631,3072800,3840000);
+                graticuleCtl2 = new OpenLayers.Control.Graticule({
+                    labelled: true,
+                    targetSize: 200
+                });
+                var mapOptions = {
+                      controls: [
+                        graticuleCtl2,
+                        new OpenLayers.Control.LayerSwitcher(),
+                        new OpenLayers.Control.PanZoomBar(),
+                        new OpenLayers.Control.Navigation()
+                      ],
+                      //scales: tempScales,
+                      maxExtent: extent,
+                      maxResolution: 50000,
+                      units: 'm',
+                      projection: 'EPSG:42304'
+                };
+                map2 = new OpenLayers.Map('map2', mapOptions);
+
+                var dm_wms = new OpenLayers.Layer.WMS( "DM Solutions Demo",
+                  "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap", {
+                     layers: "bathymetry",
+                     format: "image/png"
+                  },{
+                      singleTile: true
+                  });
+
+                map2.addLayers([dm_wms]);
+                if (!map2.getCenter()) map2.zoomToExtent(extent);
+            }
+        </script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Graticule Example</h1>
+
+        <div id="tags">
+          graticule, grid
+        </div>
+
+        <p id="shortdesc">
+            Adds a Graticule control to the map to display a grid of 
+            latitude and longitude. 
+        </p>
+
+        <div id="map" class="smallmap"></div>
+        <div id="map2" class="smallmap"></div>
+
+        <div id="docs"></div>
+        <br style="clear:both" />
+        <ul>
+            <li><a href="#" 
+                onclick="graticuleCtl1.activate(); graticuleCtl2.activate(); return false;">Activate graticule controls</a></li>
+            <li><a href="#" 
+                onclick="graticuleCtl1.deactivate(); graticuleCtl2.deactivate(); return false;">Deactivate graticule controls</a></li>
+        </ul>
+    </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/gutter.html
===================================================================
--- sandbox/ahocevar/playground/examples/gutter.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/gutter.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -33,7 +33,9 @@
   <body>
     <h1 id="title">Gutter Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        gutter, quality, tile
+    </div>
 
     <p id="shortdesc">
         Demonstrates map tiling artifacts, and OpenLayer's facility for correcting this distortion.

Modified: sandbox/ahocevar/playground/examples/highlight-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/highlight-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/highlight-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -70,6 +70,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Select and Highlight Feature Example</h1>
+    <div id="tags">
+        select, highlight, hover, onmouseover, click, vector
+    </div>
     <p id="shortdesc">
       Select features on click, highlight features on hover.
     </p>  

Modified: sandbox/ahocevar/playground/examples/hover-handler.html
===================================================================
--- sandbox/ahocevar/playground/examples/hover-handler.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/hover-handler.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -76,7 +76,7 @@
                 map = new OpenLayers.Map('map');
                 var layer = new OpenLayers.Layer.WMS(
                     'OpenLayers WMS',
-                    'http://labs.metacarta.com/wms/vmap0',
+                    'http://vmap0.tiles.osgeo.org/wms/vmap0',
                     {layers: 'basic'}
                 );
                 map.addLayers([layer]);
@@ -143,6 +143,7 @@
         <div id="west">
     
             <div id="tags">
+                hover, onmouseover, handler, listener, event, events
             </div>
     
             <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/image-layer.html
===================================================================
--- sandbox/ahocevar/playground/examples/image-layer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/image-layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -47,7 +47,9 @@
   <body onload="init()">
     <h1 id="title">Image Layer Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        image, imagelayer
+    </div>
 
     <p id="shortdesc">
         Demonstrate a single non-tiled image as a selectable base layer.

Modified: sandbox/ahocevar/playground/examples/intersects.html
===================================================================
--- sandbox/ahocevar/playground/examples/intersects.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/intersects.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -161,6 +161,9 @@
   <body onload="init()">
     <div id="leftcol">
         <h1 id="title">OpenLayers Geometry Intersection Example</h1>
+        <div id="tags">
+            intersection, geometry
+        </div>
         <p id="shortdesc">
             Use of geometry.intersects method for testing geometry intersections.
         </p>

Modified: sandbox/ahocevar/playground/examples/kamap.html
===================================================================
--- sandbox/ahocevar/playground/examples/kamap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/kamap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -26,7 +26,9 @@
   <body onload="init()">
     <h1 id="title">KaMap Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        KaMap
+    </div>
 
     <p id="shortdesc">
         Demonstrate a tiled kamap layer as the base map, which can be pre-cached for higher performance.

Modified: sandbox/ahocevar/playground/examples/kml-layer.html
===================================================================
--- sandbox/ahocevar/playground/examples/kml-layer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/kml-layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,43 +1,33 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
-    <link rel="stylesheet" href="style.css" type="text/css" />
-    <script src="../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var lon = 5;
-        var lat = 40;
-        var zoom = 5;
-        var map, layer;
+<!DOCTYPE html>
+<html>
+    <head>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+    </head>
+    <body>
+    <h1 id="title">KML Layer Example</h1>
 
-        function init(){
-            map = new OpenLayers.Map('map');
-            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
-            map.addLayer(layer);
-            map.addLayer(new OpenLayers.Layer.GML("KML", "kml/lines.kml", 
-               {
-                format: OpenLayers.Format.KML, 
-                formatOptions: {
-                  extractStyles: true, 
-                  extractAttributes: true,
-                  maxDepth: 2
-                }
-               }));
-            map.zoomToExtent(new OpenLayers.Bounds(-112.306698,36.017792,-112.03204,36.18087));
-        }
-    </script>
-  </head>
-  <body onload="init()">
-      <h1 id="title">KML Layer Example</h1>
+    <div id="tags">KML</div>
 
-      <div id="tags"></div>
-
-      <p id="shortdesc">
-          Demonstrates loading and displaying a KML file on top of a basemap.
+    <p id="shortdesc">
+        Demonstrates loading and displaying a KML file on top of a basemap.
     </p>
 
     <div id="map" class="smallmap"></div>
 
-    <div id="docs"></div>
-  </body>
+    <div id="docs">
+        <p>
+            A vector layer can be populated with features from a KML document
+            by configuring the layer with an HTTP protocol that points to the 
+            KML document and is configured with a KML format for parsing features.
+            The fixed strategy is used to load all features at once.
+        </p>
+        <p>
+            View the <a href="kml-layer.js" target="_blank">kml-layer.js</a>
+            source to see how this is done.
+        </p>
+    </div>
+    <script src="../lib/OpenLayers.js"></script>
+    <script src="kml-layer.js"></script>
+    </body>
 </html>

Copied: sandbox/ahocevar/playground/examples/kml-layer.js (from rev 10919, trunk/openlayers/examples/kml-layer.js)
===================================================================
--- sandbox/ahocevar/playground/examples/kml-layer.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/kml-layer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,22 @@
+var map = new OpenLayers.Map({
+    div: "map",
+    layers: [
+        new OpenLayers.Layer.WMS(
+            "WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0",
+            {layers: "basic"}
+        ),
+        new OpenLayers.Layer.Vector("KML", {
+            strategies: [new OpenLayers.Strategy.Fixed()],
+            protocol: new OpenLayers.Protocol.HTTP({
+                url: "kml/lines.kml",
+                format: new OpenLayers.Format.KML({
+                    extractStyles: true, 
+                    extractAttributes: true,
+                    maxDepth: 2
+                })
+            })
+        })
+    ],
+    center: new OpenLayers.LonLat(-112.169, 36.099),
+    zoom: 11
+});

Copied: sandbox/ahocevar/playground/examples/kml-track.html (from rev 10919, trunk/openlayers/examples/kml-track.html)
===================================================================
--- sandbox/ahocevar/playground/examples/kml-track.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/kml-track.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers KLM Track Parsing Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <style>
+            .olControlAttribution {
+                bottom: 2px;
+            }
+        </style>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="kml-track.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Parsing gx:Track in KML</h1>
+        <p id="shortdesc">
+            Demonstrates parsing of gx:Track elements from KML.
+        </p>
+        <div id="tags">
+            KML, parser, parsing, tracks
+        </div>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                If a KML document contains <code>&lt;gx:Track&gt;</code> 
+                elements and the extractTracks property is set true on the 
+                parer, features will be created that represent track points.
+                Each feature will have a when attribute that contains the 
+                value of the relevant <code>&lt;when&gt;</code> element from 
+                the track.
+            </p>
+            <p>
+                View the <a href="kml-track.js" target="_blank">kml-track.js</a>
+                source to see how this is done.
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/kml-track.js (from rev 10919, trunk/openlayers/examples/kml-track.js)
===================================================================
--- sandbox/ahocevar/playground/examples/kml-track.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/kml-track.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,40 @@
+var map;
+
+function init() {
+
+    var mercator = new OpenLayers.Projection("EPSG:900913");
+    var geographic = new OpenLayers.Projection("EPSG:4326");
+
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: mercator,
+        layers: [
+            new OpenLayers.Layer.OSM(),
+            new OpenLayers.Layer.Vector("Aircraft Locations", {
+                projection: geographic,
+                strategies: [new OpenLayers.Strategy.Fixed()],
+                protocol: new OpenLayers.Protocol.HTTP({
+                    url: "kml-track.kml",
+                    format: new OpenLayers.Format.KML({
+                        extractTracks: true,
+                        trackAttributes: ["speed"]
+                    })
+                }),
+                styleMap: new OpenLayers.StyleMap({
+                    "default": new OpenLayers.Style({
+                        graphicName: "circle",
+                        pointRadius: 2,
+                        fillOpacity: 0.5,
+                        fillColor: "#ffcc66",
+                        strokeColor: "#666633",
+                        strokeWidth: 1,
+                    })
+                })
+            })
+        ],
+        center: new OpenLayers.LonLat(-93.2735, 44.8349).transform(geographic, mercator),
+        zoom: 8
+    });
+    
+};
+

Copied: sandbox/ahocevar/playground/examples/kml-track.kml (from rev 10919, trunk/openlayers/examples/kml-track.kml)
===================================================================
--- sandbox/ahocevar/playground/examples/kml-track.kml	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/kml-track.kml	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,3359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
+<Document>
+<Camera>
+  <gx:TimeStamp>
+    <when>2010-05-01T13:00:00-05:00</when>
+  </gx:TimeStamp>
+  <longitude>-93.2207</longitude>
+  <latitude>44.882</latitude>
+  <altitude>50000</altitude>
+  <heading>0</heading>
+  <tilt>0</tilt>
+</Camera>
+<Style id="arrival">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff0000ff</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id="departure">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff00ff00</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id="overflight">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff222222</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id='rmt'>
+  <LabelStyle>
+    <color>ff0000cc</color>
+    <colorMode>normal</colorMode>
+    <scale>1</scale>
+  </LabelStyle>
+</Style>
+
+<name>Flight Tracks</name>
+<Folder>
+  <name>Arrivals</name>
+<Placemark>
+  <name>B752</name>
+  <adflag>A</adflag>
+  <flightid>DAL2973</flightid>
+  <styleUrl>#arrival</styleUrl>
+</Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>TCF7521</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:04-05</when>
+    <when>2010-05-01T13:00:09-05</when>
+    <when>2010-05-01T13:00:13-05</when>
+    <when>2010-05-01T13:00:18-05</when>
+    <when>2010-05-01T13:00:23-05</when>
+    <when>2010-05-01T13:00:27-05</when>
+    <when>2010-05-01T13:00:32-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:41-05</when>
+    <when>2010-05-01T13:00:46-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:55-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <when>2010-05-01T13:01:05-05</when>
+    <when>2010-05-01T13:01:09-05</when>
+    <when>2010-05-01T13:01:14-05</when>
+    <when>2010-05-01T13:01:19-05</when>
+    <when>2010-05-01T13:01:23-05</when>
+    <when>2010-05-01T13:01:28-05</when>
+    <when>2010-05-01T13:01:33-05</when>
+    <when>2010-05-01T13:01:37-05</when>
+    <when>2010-05-01T13:01:42-05</when>
+    <when>2010-05-01T13:01:47-05</when>
+    <when>2010-05-01T13:01:51-05</when>
+    <when>2010-05-01T13:01:56-05</when>
+    <when>2010-05-01T13:02:00-05</when>
+    <when>2010-05-01T13:02:05-05</when>
+    <when>2010-05-01T13:02:10-05</when>
+    <when>2010-05-01T13:02:14-05</when>
+    <when>2010-05-01T13:02:19-05</when>
+    <when>2010-05-01T13:02:24-05</when>
+    <when>2010-05-01T13:02:28-05</when>
+    <when>2010-05-01T13:02:33-05</when>
+    <when>2010-05-01T13:02:38-05</when>
+    <when>2010-05-01T13:02:42-05</when>
+    <when>2010-05-01T13:02:47-05</when>
+    <when>2010-05-01T13:02:52-05</when>
+    <when>2010-05-01T13:02:56-05</when>
+    <when>2010-05-01T13:03:01-05</when>
+    <when>2010-05-01T13:03:06-05</when>
+    <when>2010-05-01T13:03:10-05</when>
+    <when>2010-05-01T13:03:15-05</when>
+    <when>2010-05-01T13:03:20-05</when>
+    <when>2010-05-01T13:03:24-05</when>
+    <when>2010-05-01T13:03:29-05</when>
+    <when>2010-05-01T13:03:33-05</when>
+    <when>2010-05-01T13:03:38-05</when>
+    <when>2010-05-01T13:03:43-05</when>
+    <when>2010-05-01T13:03:47-05</when>
+    <when>2010-05-01T13:03:52-05</when>
+    <when>2010-05-01T13:03:57-05</when>
+    <when>2010-05-01T13:04:01-05</when>
+    <when>2010-05-01T13:04:06-05</when>
+    <when>2010-05-01T13:04:11-05</when>
+    <when>2010-05-01T13:04:15-05</when>
+    <when>2010-05-01T13:04:20-05</when>
+    <when>2010-05-01T13:04:24-05</when>
+    <when>2010-05-01T13:04:29-05</when>
+    <when>2010-05-01T13:04:34-05</when>
+    <when>2010-05-01T13:04:38-05</when>
+    <when>2010-05-01T13:04:43-05</when>
+    <when>2010-05-01T13:04:48-05</when>
+    <when>2010-05-01T13:04:52-05</when>
+    <when>2010-05-01T13:04:57-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.3806146339391 44.8823651507134 2743</gx:coord>
+    <gx:coord>-93.3773041814209 44.887531728655 2743</gx:coord>
+    <gx:coord>-93.3742856469083 44.8942041806778 2743</gx:coord>
+    <gx:coord>-93.3722375106026 44.9009231720158 2743</gx:coord>
+    <gx:coord>-93.3711934089417 44.9077495987718 2712</gx:coord>
+    <gx:coord>-93.3707288919852 44.9145219645156 2712</gx:coord>
+    <gx:coord>-93.3703882714439 44.921240089024 2682</gx:coord>
+    <gx:coord>-93.3700882719793 44.9278850664392 2682</gx:coord>
+    <gx:coord>-93.369810041597 44.934389356737 2651</gx:coord>
+    <gx:coord>-93.3696836566166 44.9408553642446 2651</gx:coord>
+    <gx:coord>-93.3695425129226 44.9473561165969 2621</gx:coord>
+    <gx:coord>-93.3693185423471 44.9537360442564 2621</gx:coord>
+    <gx:coord>-93.3693194298816 44.9599975904123 2590</gx:coord>
+    <gx:coord>-93.3694031671108 44.9661411653607 2590</gx:coord>
+    <gx:coord>-93.3693840701674 44.9721433662718 2560</gx:coord>
+    <gx:coord>-93.3692180132117 44.9781295444861 2530</gx:coord>
+    <gx:coord>-93.3691451194519 44.9840448037796 2530</gx:coord>
+    <gx:coord>-93.3691016671806 44.9899713582099 2499</gx:coord>
+    <gx:coord>-93.3689494749454 44.9958413836039 2469</gx:coord>
+    <gx:coord>-93.3687664425911 45.0015898503441 2469</gx:coord>
+    <gx:coord>-93.3686331392066 45.0072067405394 2438</gx:coord>
+    <gx:coord>-93.368599726987 45.0127741072778 2438</gx:coord>
+    <gx:coord>-93.3686335399802 45.0181909829245 2408</gx:coord>
+    <gx:coord>-93.3686494842522 45.0234209328517 2377</gx:coord>
+    <gx:coord>-93.3684675008434 45.0286421277802 2377</gx:coord>
+    <gx:coord>-93.3683004008135 45.0337736830037 2347</gx:coord>
+    <gx:coord>-93.3682154531592 45.0388787100883 2347</gx:coord>
+    <gx:coord>-93.3683732351584 45.0439463933312 2316</gx:coord>
+    <gx:coord>-93.3684142261585 45.0490625635571 2286</gx:coord>
+    <gx:coord>-93.368143196103 45.0541794203461 2286</gx:coord>
+    <gx:coord>-93.367535632513 45.0592327492686 2255</gx:coord>
+    <gx:coord>-93.3659957839062 45.0642802941983 2225</gx:coord>
+    <gx:coord>-93.3633687278349 45.0690971409498 2194</gx:coord>
+    <gx:coord>-93.3595471289752 45.0735562314314 2164</gx:coord>
+    <gx:coord>-93.354507806741 45.0775832626329 2133</gx:coord>
+    <gx:coord>-93.3485772854268 45.0808293296313 2103</gx:coord>
+    <gx:coord>-93.3421088995911 45.0832469498159 2072</gx:coord>
+    <gx:coord>-93.3351951799649 45.0848109253641 2042</gx:coord>
+    <gx:coord>-93.3280418232705 45.0854246893649 2011</gx:coord>
+    <gx:coord>-93.3209037884868 45.085161376704 1981</gx:coord>
+    <gx:coord>-93.3144723535558 45.0839515303103 1920</gx:coord>
+    <gx:coord>-93.3088086501455 45.0819151336509 1859</gx:coord>
+    <gx:coord>-93.3036917357871 45.0792511074707 1828</gx:coord>
+    <gx:coord>-93.2993102013018 45.0761649196153 1798</gx:coord>
+    <gx:coord>-93.2958637974439 45.0728030913231 1768</gx:coord>
+    <gx:coord>-93.2932247031583 45.0693710694135 1737</gx:coord>
+    <gx:coord>-93.2910486937635 45.0659261208859 1707</gx:coord>
+    <gx:coord>-93.2888955993508 45.0625213360315 1646</gx:coord>
+    <gx:coord>-93.2867217490801 45.0591551785287 1615</gx:coord>
+    <gx:coord>-93.2847336413534 45.0557231883841 1554</gx:coord>
+    <gx:coord>-93.28312407167 45.0523278244803 1493</gx:coord>
+    <gx:coord>-93.2820244198825 45.0489932635616 1463</gx:coord>
+    <gx:coord>-93.280973634799 45.045699024227 1432</gx:coord>
+    <gx:coord>-93.2799787649067 45.0423671615142 1402</gx:coord>
+    <gx:coord>-93.2791066054659 45.0390946347227 1341</gx:coord>
+    <gx:coord>-93.2784127726862 45.0358634874951 1310</gx:coord>
+    <gx:coord>-93.2779112647802 45.0326008999249 1249</gx:coord>
+    <gx:coord>-93.2774525889269 45.029330264578 1219</gx:coord>
+    <gx:coord>-93.2770784201422 45.0260213245381 1188</gx:coord>
+    <gx:coord>-93.2766188240203 45.0227403501287 1158</gx:coord>
+    <gx:coord>-93.275816823547 45.0195461585342 1127</gx:coord>
+    <gx:coord>-93.2748914840222 45.0163603671711 1066</gx:coord>
+    <gx:coord>-93.2740540575136 45.0131542183389 1036</gx:coord>
+    <gx:coord>-93.2733145981662 45.010040506328 1006</gx:coord>
+    <gx:coord>-93.2724700860766 45.0070495365802 975</gx:coord>
+    <gx:coord>-93.2720166974715 45.0052389419128 957</gx:coord>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>40 0 0</gx:angles>
+    <gx:angles>50 0 0</gx:angles>
+    <gx:angles>60 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>80 0 0</gx:angles>
+    <gx:angles>90 0 0</gx:angles>
+    <gx:angles>100 0 0</gx:angles>
+    <gx:angles>110 0 0</gx:angles>
+    <gx:angles>120 0 0</gx:angles>
+    <gx:angles>130 0 0</gx:angles>
+    <gx:angles>140 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <speed>376</speed>
+    <speed>367</speed>
+    <speed>361</speed>
+    <speed>371</speed>
+    <speed>367</speed>
+    <speed>363</speed>
+    <speed>359</speed>
+    <speed>356</speed>
+    <speed>352</speed>
+    <speed>347</speed>
+    <speed>343</speed>
+    <speed>339</speed>
+    <speed>334</speed>
+    <speed>329</speed>
+    <speed>326</speed>
+    <speed>321</speed>
+    <speed>318</speed>
+    <speed>315</speed>
+    <speed>311</speed>
+    <speed>307</speed>
+    <speed>301</speed>
+    <speed>294</speed>
+    <speed>289</speed>
+    <speed>295</speed>
+    <speed>280</speed>
+    <speed>277</speed>
+    <speed>287</speed>
+    <speed>275</speed>
+    <speed>275</speed>
+    <speed>276</speed>
+    <speed>277</speed>
+    <speed>279</speed>
+    <speed>281</speed>
+    <speed>282</speed>
+    <speed>282</speed>
+    <speed>281</speed>
+    <speed>280</speed>
+    <speed>274</speed>
+    <speed>266</speed>
+    <speed>260</speed>
+    <speed>254</speed>
+    <speed>244</speed>
+    <speed>235</speed>
+    <speed>235</speed>
+    <speed>219</speed>
+    <speed>212</speed>
+    <speed>214</speed>
+    <speed>201</speed>
+    <speed>197</speed>
+    <speed>193</speed>
+    <speed>190</speed>
+    <speed>187</speed>
+    <speed>183</speed>
+    <speed>180</speed>
+    <speed>186</speed>
+    <speed>178</speed>
+    <speed>177</speed>
+    <speed>183</speed>
+    <speed>177</speed>
+    <speed>176</speed>
+    <speed>175</speed>
+    <speed>173</speed>
+    <speed>171</speed>
+    <speed>165</speed>
+    <speed>166</speed>
+    <speed>167</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>BE33</name>
+  <adflag>A</adflag>
+  <flightid>N38175</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:02-05</when>
+    <when>2010-05-01T13:00:07-05</when>
+    <when>2010-05-01T13:00:12-05</when>
+    <when>2010-05-01T13:00:16-05</when>
+    <when>2010-05-01T13:00:21-05</when>
+    <when>2010-05-01T13:00:25-05</when>
+    <when>2010-05-01T13:00:30-05</when>
+    <when>2010-05-01T13:00:35-05</when>
+    <when>2010-05-01T13:00:39-05</when>
+    <when>2010-05-01T13:00:44-05</when>
+    <when>2010-05-01T13:00:49-05</when>
+    <when>2010-05-01T13:00:53-05</when>
+    <when>2010-05-01T13:00:58-05</when>
+    <when>2010-05-01T13:01:03-05</when>
+    <when>2010-05-01T13:01:07-05</when>
+    <when>2010-05-01T13:01:12-05</when>
+    <when>2010-05-01T13:01:16-05</when>
+    <when>2010-05-01T13:01:21-05</when>
+    <when>2010-05-01T13:01:26-05</when>
+    <when>2010-05-01T13:01:30-05</when>
+    <when>2010-05-01T13:01:35-05</when>
+    <when>2010-05-01T13:01:40-05</when>
+    <when>2010-05-01T13:01:44-05</when>
+    <when>2010-05-01T13:01:49-05</when>
+    <when>2010-05-01T13:01:54-05</when>
+    <when>2010-05-01T13:01:58-05</when>
+    <when>2010-05-01T13:02:03-05</when>
+    <when>2010-05-01T13:02:08-05</when>
+    <when>2010-05-01T13:02:12-05</when>
+    <when>2010-05-01T13:02:17-05</when>
+    <when>2010-05-01T13:02:21-05</when>
+    <when>2010-05-01T13:02:26-05</when>
+    <when>2010-05-01T13:02:31-05</when>
+    <when>2010-05-01T13:02:35-05</when>
+    <when>2010-05-01T13:02:40-05</when>
+    <when>2010-05-01T13:02:45-05</when>
+    <when>2010-05-01T13:02:49-05</when>
+    <when>2010-05-01T13:02:54-05</when>
+    <when>2010-05-01T13:02:59-05</when>
+    <when>2010-05-01T13:03:03-05</when>
+    <when>2010-05-01T13:03:08-05</when>
+    <when>2010-05-01T13:03:13-05</when>
+    <when>2010-05-01T13:03:17-05</when>
+    <when>2010-05-01T13:03:22-05</when>
+    <when>2010-05-01T13:03:27-05</when>
+    <when>2010-05-01T13:03:31-05</when>
+    <when>2010-05-01T13:03:36-05</when>
+    <when>2010-05-01T13:03:40-05</when>
+    <when>2010-05-01T13:03:45-05</when>
+    <when>2010-05-01T13:03:50-05</when>
+    <when>2010-05-01T13:03:54-05</when>
+    <when>2010-05-01T13:03:59-05</when>
+    <when>2010-05-01T13:04:04-05</when>
+    <when>2010-05-01T13:04:08-05</when>
+    <when>2010-05-01T13:04:13-05</when>
+    <when>2010-05-01T13:04:18-05</when>
+    <when>2010-05-01T13:04:22-05</when>
+    <when>2010-05-01T13:04:27-05</when>
+    <when>2010-05-01T13:04:32-05</when>
+    <when>2010-05-01T13:04:36-05</when>
+    <when>2010-05-01T13:04:41-05</when>
+    <when>2010-05-01T13:04:46-05</when>
+    <when>2010-05-01T13:04:50-05</when>
+    <when>2010-05-01T13:04:55-05</when>
+    <when>2010-05-01T13:04:59-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.0144637208028 44.6541474764804 1006</gx:coord>
+    <gx:coord>-93.0162681345228 44.6547274296664 1006</gx:coord>
+    <gx:coord>-93.0196734868835 44.6559915702004 975</gx:coord>
+    <gx:coord>-93.0231899415297 44.657188463998 945</gx:coord>
+    <gx:coord>-93.0267619421777 44.6582849847887 945</gx:coord>
+    <gx:coord>-93.0302021384369 44.6594728216183 914</gx:coord>
+    <gx:coord>-93.0338776768471 44.6606515995762 914</gx:coord>
+    <gx:coord>-93.0375866343814 44.6618806707998 884</gx:coord>
+    <gx:coord>-93.0411146687035 44.6632657982455 884</gx:coord>
+    <gx:coord>-93.0447829038862 44.6646495821585 884</gx:coord>
+    <gx:coord>-93.0486933143218 44.6659856209571 914</gx:coord>
+    <gx:coord>-93.0525604964428 44.6672664774449 884</gx:coord>
+    <gx:coord>-93.0559892061682 44.6686325276705 884</gx:coord>
+    <gx:coord>-93.0595122787868 44.6700360197293 884</gx:coord>
+    <gx:coord>-93.0633002358996 44.6714677760105 884</gx:coord>
+    <gx:coord>-93.0669378047758 44.6729112967405 884</gx:coord>
+    <gx:coord>-93.0703945562928 44.6742924439153 884</gx:coord>
+    <gx:coord>-93.0739155391788 44.675662416586 853</gx:coord>
+    <gx:coord>-93.0775155708379 44.677089176175 853</gx:coord>
+    <gx:coord>-93.0809933799389 44.6786451836444 884</gx:coord>
+    <gx:coord>-93.0844890660754 44.6803751966183 884</gx:coord>
+    <gx:coord>-93.0880299182291 44.6822044360867 884</gx:coord>
+    <gx:coord>-93.0915094168569 44.6840756286875 884</gx:coord>
+    <gx:coord>-93.0948937737562 44.6859682015167 853</gx:coord>
+    <gx:coord>-93.0981262632978 44.6879373605934 853</gx:coord>
+    <gx:coord>-93.101454986707 44.6899364101225 792</gx:coord>
+    <gx:coord>-93.1050116792292 44.6917700662615 823</gx:coord>
+    <gx:coord>-93.1086488406447 44.6935571270851 792</gx:coord>
+    <gx:coord>-93.1123714592033 44.6950844029867 792</gx:coord>
+    <gx:coord>-93.1160669441025 44.6961547755501 792</gx:coord>
+    <gx:coord>-93.1198701422529 44.6969844340505 823</gx:coord>
+    <gx:coord>-93.1236851662824 44.6978291490322 823</gx:coord>
+    <gx:coord>-93.1274225659796 44.6986718065416 823</gx:coord>
+    <gx:coord>-93.1311942704264 44.6993984412966 853</gx:coord>
+    <gx:coord>-93.1349381107515 44.6999999769729 823</gx:coord>
+    <gx:coord>-93.1389399866831 44.7004676966664 823</gx:coord>
+    <gx:coord>-93.1429353283304 44.7008467726719 792</gx:coord>
+    <gx:coord>-93.1467319575358 44.7012413854652 792</gx:coord>
+    <gx:coord>-93.1499628617348 44.701745671311 256</gx:coord>
+    <gx:coord>-93.153336892791 44.7021601177798 823</gx:coord>
+    <gx:coord>-93.1573155649233 44.7025431241565 823</gx:coord>
+    <gx:coord>-93.1612285414011 44.7030631821633 853</gx:coord>
+    <gx:coord>-93.1650893906409 44.7036343060226 823</gx:coord>
+    <gx:coord>-93.168735434804 44.7041440584898 823</gx:coord>
+    <gx:coord>-93.1724202011042 44.7046128372079 823</gx:coord>
+    <gx:coord>-93.1761398862948 44.7051091435166 792</gx:coord>
+    <gx:coord>-93.1796630936383 44.7055777394683 792</gx:coord>
+    <gx:coord>-93.1832380178971 44.7060406072565 823</gx:coord>
+    <gx:coord>-93.1866638342882 44.7066093849988 823</gx:coord>
+    <gx:coord>-93.1899087146892 44.7071801343989 823</gx:coord>
+    <gx:coord>-93.193359587537 44.7076743817907 823</gx:coord>
+    <gx:coord>-93.1967000778824 44.7081822996347 823</gx:coord>
+    <gx:coord>-93.1999669003743 44.7087817760063 823</gx:coord>
+    <gx:coord>-93.2034706963438 44.7093224014614 823</gx:coord>
+    <gx:coord>-93.2071875434321 44.7097715459537 823</gx:coord>
+    <gx:coord>-93.2107765241539 44.7103153755538 823</gx:coord>
+    <gx:coord>-93.2143295791529 44.7108254548145 823</gx:coord>
+    <gx:coord>-93.2178486234666 44.7112392078782 792</gx:coord>
+    <gx:coord>-93.2211867867256 44.7116696952986 823</gx:coord>
+    <gx:coord>-93.2243580018062 44.7121483598855 823</gx:coord>
+    <gx:coord>-93.2273334445383 44.712639974576 823</gx:coord>
+    <gx:coord>-93.230487243959 44.7131510651587 823</gx:coord>
+    <gx:coord>-93.233844667064 44.7137558527546 823</gx:coord>
+    <gx:coord>-93.2369967848442 44.714497155781 823</gx:coord>
+    <gx:coord>-93.2401184808953 44.7154113173173 823</gx:coord>
+    <gx:coord>-93.2431805770012 44.7167484248595 792</gx:coord>
+    <gx:coord>-93.2437334091088 44.7170975413723 792</gx:coord>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <speed>150</speed>
+    <speed>156</speed>
+    <speed>152</speed>
+    <speed>156</speed>
+    <speed>151</speed>
+    <speed>152</speed>
+    <speed>160</speed>
+    <speed>157</speed>
+    <speed>159</speed>
+    <speed>158</speed>
+    <speed>158</speed>
+    <speed>160</speed>
+    <speed>160</speed>
+    <speed>158</speed>
+    <speed>162</speed>
+    <speed>157</speed>
+    <speed>158</speed>
+    <speed>164</speed>
+    <speed>159</speed>
+    <speed>161</speed>
+    <speed>163</speed>
+    <speed>164</speed>
+    <speed>166</speed>
+    <speed>167</speed>
+    <speed>167</speed>
+    <speed>166</speed>
+    <speed>164</speed>
+    <speed>163</speed>
+    <speed>166</speed>
+    <speed>157</speed>
+    <speed>154</speed>
+    <speed>157</speed>
+    <speed>152</speed>
+    <speed>152</speed>
+    <speed>151</speed>
+    <speed>147</speed>
+    <speed>144</speed>
+    <speed>146</speed>
+    <speed>145</speed>
+    <speed>145</speed>
+    <speed>144</speed>
+    <speed>146</speed>
+    <speed>148</speed>
+    <speed>145</speed>
+    <speed>143</speed>
+    <speed>146</speed>
+    <speed>138</speed>
+    <speed>137</speed>
+    <speed>140</speed>
+    <speed>133</speed>
+    <speed>133</speed>
+    <speed>135</speed>
+    <speed>137</speed>
+    <speed>137</speed>
+    <speed>138</speed>
+    <speed>138</speed>
+    <speed>136</speed>
+    <speed>131</speed>
+    <speed>129</speed>
+    <speed>128</speed>
+    <speed>126</speed>
+    <speed>126</speed>
+    <speed>133</speed>
+    <speed>132</speed>
+    <speed>136</speed>
+    <speed>139</speed>
+    <speed>136</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>A319</name>
+  <adflag>A</adflag>
+  <flightid>DAL1588</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:04-05</when>
+    <when>2010-05-01T13:00:08-05</when>
+    <when>2010-05-01T13:00:13-05</when>
+    <when>2010-05-01T13:00:18-05</when>
+    <when>2010-05-01T13:00:22-05</when>
+    <when>2010-05-01T13:00:27-05</when>
+    <when>2010-05-01T13:00:31-05</when>
+    <when>2010-05-01T13:00:36-05</when>
+    <when>2010-05-01T13:00:41-05</when>
+    <when>2010-05-01T13:00:45-05</when>
+    <when>2010-05-01T13:00:50-05</when>
+    <when>2010-05-01T13:00:55-05</when>
+    <when>2010-05-01T13:00:59-05</when>
+    <when>2010-05-01T13:01:04-05</when>
+    <when>2010-05-01T13:01:09-05</when>
+    <when>2010-05-01T13:01:13-05</when>
+    <when>2010-05-01T13:01:18-05</when>
+    <when>2010-05-01T13:01:22-05</when>
+    <when>2010-05-01T13:01:27-05</when>
+    <when>2010-05-01T13:01:32-05</when>
+    <when>2010-05-01T13:01:36-05</when>
+    <when>2010-05-01T13:01:41-05</when>
+    <when>2010-05-01T13:01:46-05</when>
+    <when>2010-05-01T13:01:50-05</when>
+    <when>2010-05-01T13:01:55-05</when>
+    <when>2010-05-01T13:02:00-05</when>
+    <when>2010-05-01T13:02:04-05</when>
+    <when>2010-05-01T13:02:09-05</when>
+    <when>2010-05-01T13:02:13-05</when>
+    <when>2010-05-01T13:02:18-05</when>
+    <when>2010-05-01T13:02:23-05</when>
+    <when>2010-05-01T13:02:27-05</when>
+    <when>2010-05-01T13:02:32-05</when>
+    <when>2010-05-01T13:02:37-05</when>
+    <when>2010-05-01T13:02:41-05</when>
+    <when>2010-05-01T13:02:46-05</when>
+    <when>2010-05-01T13:02:51-05</when>
+    <when>2010-05-01T13:02:55-05</when>
+    <when>2010-05-01T13:03:00-05</when>
+    <when>2010-05-01T13:03:05-05</when>
+    <when>2010-05-01T13:03:09-05</when>
+    <when>2010-05-01T13:03:14-05</when>
+    <when>2010-05-01T13:03:19-05</when>
+    <when>2010-05-01T13:03:23-05</when>
+    <when>2010-05-01T13:03:28-05</when>
+    <when>2010-05-01T13:03:33-05</when>
+    <when>2010-05-01T13:03:37-05</when>
+    <when>2010-05-01T13:03:42-05</when>
+    <when>2010-05-01T13:03:47-05</when>
+    <when>2010-05-01T13:03:51-05</when>
+    <when>2010-05-01T13:03:56-05</when>
+    <when>2010-05-01T13:04:01-05</when>
+    <when>2010-05-01T13:04:05-05</when>
+    <when>2010-05-01T13:04:10-05</when>
+    <when>2010-05-01T13:04:15-05</when>
+    <when>2010-05-01T13:04:19-05</when>
+    <when>2010-05-01T13:04:24-05</when>
+    <when>2010-05-01T13:04:29-05</when>
+    <when>2010-05-01T13:04:33-05</when>
+    <when>2010-05-01T13:04:38-05</when>
+    <when>2010-05-01T13:04:42-05</when>
+    <when>2010-05-01T13:04:47-05</when>
+    <when>2010-05-01T13:04:52-05</when>
+    <when>2010-05-01T13:04:56-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.6927825194056 44.7952011849485 3011</gx:coord>
+    <gx:coord>-93.6850156681578 44.7968042586582 2987</gx:coord>
+    <gx:coord>-93.6752785488692 44.7990458605003 2956</gx:coord>
+    <gx:coord>-93.6657083011645 44.8014897663497 2926</gx:coord>
+    <gx:coord>-93.6560029615388 44.803768841381 2865</gx:coord>
+    <gx:coord>-93.6462045264035 44.8058749817725 2834</gx:coord>
+    <gx:coord>-93.6365671200126 44.8080848199989 2804</gx:coord>
+    <gx:coord>-93.6269933807039 44.8102767000109 2773</gx:coord>
+    <gx:coord>-93.6175405757462 44.8123960709083 2743</gx:coord>
+    <gx:coord>-93.6082528975965 44.8146455509748 2743</gx:coord>
+    <gx:coord>-93.599077315807 44.816765612372 2743</gx:coord>
+    <gx:coord>-93.5899428762254 44.8186933623744 2743</gx:coord>
+    <gx:coord>-93.5809104439923 44.8205403457841 2743</gx:coord>
+    <gx:coord>-93.5720785209701 44.8224608846058 2743</gx:coord>
+    <gx:coord>-93.5634871751281 44.8245259755976 2743</gx:coord>
+    <gx:coord>-93.5549873819943 44.8264288380043 2743</gx:coord>
+    <gx:coord>-93.5465301417765 44.828146963076 2743</gx:coord>
+    <gx:coord>-93.5382602633868 44.8299225976982 2743</gx:coord>
+    <gx:coord>-93.5299909540853 44.8317218299661 2743</gx:coord>
+    <gx:coord>-93.5217290971281 44.8335486849228 2743</gx:coord>
+    <gx:coord>-93.5135254319341 44.8354478299135 2743</gx:coord>
+    <gx:coord>-93.5052463800971 44.8374557781543 2743</gx:coord>
+    <gx:coord>-93.4970241378696 44.8393862625467 2743</gx:coord>
+    <gx:coord>-93.4888916549316 44.8410628089589 2743</gx:coord>
+    <gx:coord>-93.48064759949 44.8427813728647 2743</gx:coord>
+    <gx:coord>-93.4722750572418 44.8445241451071 2712</gx:coord>
+    <gx:coord>-93.4639262889443 44.8463688032483 2743</gx:coord>
+    <gx:coord>-93.4556378890352 44.8482208160082 2743</gx:coord>
+    <gx:coord>-93.447407568623 44.8500947691895 2743</gx:coord>
+    <gx:coord>-93.4393642055014 44.8523517774191 2743</gx:coord>
+    <gx:coord>-93.4316071047585 44.8551246076581 2743</gx:coord>
+    <gx:coord>-93.4244028068218 44.8584705613027 2743</gx:coord>
+    <gx:coord>-93.4178621631751 44.8625068369064 2743</gx:coord>
+    <gx:coord>-93.412146307774 44.867174139387 2743</gx:coord>
+    <gx:coord>-93.4075995385136 44.8722931076546 2743</gx:coord>
+    <gx:coord>-93.4039820359465 44.8777375352403 2743</gx:coord>
+    <gx:coord>-93.4016072978871 44.8833117162528 2743</gx:coord>
+    <gx:coord>-93.4005924913122 44.8890542850171 2743</gx:coord>
+    <gx:coord>-93.4005563275156 44.8948199828389 2712</gx:coord>
+    <gx:coord>-93.401452844832 44.9002595243996 2682</gx:coord>
+    <gx:coord>-93.4032713926758 44.905357711587 2651</gx:coord>
+    <gx:coord>-93.4058979070097 44.9101654056189 2621</gx:coord>
+    <gx:coord>-93.4092802306306 44.9145600538157 2590</gx:coord>
+    <gx:coord>-93.4134192058116 44.9185233235535 2530</gx:coord>
+    <gx:coord>-93.4181155067703 44.9222086893794 2499</gx:coord>
+    <gx:coord>-93.4230280156053 44.9256003980833 2469</gx:coord>
+    <gx:coord>-93.4278299295206 44.9290448932076 2469</gx:coord>
+    <gx:coord>-93.4322535173586 44.9329315139411 2438</gx:coord>
+    <gx:coord>-93.4361102418566 44.9372336672133 2438</gx:coord>
+    <gx:coord>-93.4389664177141 44.9421107629499 2438</gx:coord>
+    <gx:coord>-93.4407103051748 44.9473646343685 2438</gx:coord>
+    <gx:coord>-93.4416032158439 44.9527430754122 2408</gx:coord>
+    <gx:coord>-93.4419308994101 44.9581538029148 2408</gx:coord>
+    <gx:coord>-93.4419313717103 44.9636029026039 2377</gx:coord>
+    <gx:coord>-93.4417378352424 44.9690628839115 2347</gx:coord>
+    <gx:coord>-93.4415990458805 44.9744028948354 2347</gx:coord>
+    <gx:coord>-93.4414478519305 44.9796663959001 2316</gx:coord>
+    <gx:coord>-93.4413557290344 44.9848518867987 2316</gx:coord>
+    <gx:coord>-93.4412896011133 44.9899566690879 2316</gx:coord>
+    <gx:coord>-93.4411625354696 44.9949926823698 2286</gx:coord>
+    <gx:coord>-93.4411216122071 45.000018474264 2225</gx:coord>
+    <gx:coord>-93.4409537301264 45.0051267594771 2194</gx:coord>
+    <gx:coord>-93.4408143120176 45.0101358999996 2133</gx:coord>
+    <gx:coord>-93.4405516208864 45.0150761969136 2103</gx:coord>
+    <gx:coord>-93.4397025278204 45.0199965135021 2042</gx:coord>
+    <gx:coord>-93.4384243921567 45.02391596133 1993.2</gx:coord>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>60 0 0</gx:angles>
+    <gx:angles>50 0 0</gx:angles>
+    <gx:angles>50 0 0</gx:angles>
+    <gx:angles>40 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>360 0 0</gx:angles>
+    <gx:angles>350 0 0</gx:angles>
+    <gx:angles>340 0 0</gx:angles>
+    <gx:angles>340 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>340 0 0</gx:angles>
+    <gx:angles>350 0 0</gx:angles>
+    <gx:angles>350 0 0</gx:angles>
+    <gx:angles>360 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <speed>390</speed>
+    <speed>383</speed>
+    <speed>397</speed>
+    <speed>390</speed>
+    <speed>405</speed>
+    <speed>388</speed>
+    <speed>386</speed>
+    <speed>397</speed>
+    <speed>377</speed>
+    <speed>373</speed>
+    <speed>367</speed>
+    <speed>362</speed>
+    <speed>357</speed>
+    <speed>350</speed>
+    <speed>345</speed>
+    <speed>353</speed>
+    <speed>336</speed>
+    <speed>334</speed>
+    <speed>346</speed>
+    <speed>332</speed>
+    <speed>331</speed>
+    <speed>330</speed>
+    <speed>331</speed>
+    <speed>332</speed>
+    <speed>331</speed>
+    <speed>331</speed>
+    <speed>345</speed>
+    <speed>333</speed>
+    <speed>332</speed>
+    <speed>344</speed>
+    <speed>331</speed>
+    <speed>331</speed>
+    <speed>329</speed>
+    <speed>326</speed>
+    <speed>324</speed>
+    <speed>320</speed>
+    <speed>314</speed>
+    <speed>307</speed>
+    <speed>298</speed>
+    <speed>291</speed>
+    <speed>284</speed>
+    <speed>276</speed>
+    <speed>271</speed>
+    <speed>268</speed>
+    <speed>266</speed>
+    <speed>267</speed>
+    <speed>270</speed>
+    <speed>274</speed>
+    <speed>279</speed>
+    <speed>283</speed>
+    <speed>288</speed>
+    <speed>291</speed>
+    <speed>292</speed>
+    <speed>290</speed>
+    <speed>288</speed>
+    <speed>286</speed>
+    <speed>281</speed>
+    <speed>278</speed>
+    <speed>286</speed>
+    <speed>273</speed>
+    <speed>271</speed>
+    <speed>280</speed>
+    <speed>270</speed>
+    <speed>274</speed>
+    <speed>263</speed>
+    <speed>268</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E145</name>
+  <adflag>A</adflag>
+  <flightid>CHQ1453</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:02-05</when>
+    <when>2010-05-01T13:01:06-05</when>
+    <when>2010-05-01T13:01:11-05</when>
+    <when>2010-05-01T13:01:15-05</when>
+    <when>2010-05-01T13:01:20-05</when>
+    <when>2010-05-01T13:01:25-05</when>
+    <when>2010-05-01T13:01:29-05</when>
+    <when>2010-05-01T13:01:34-05</when>
+    <when>2010-05-01T13:01:39-05</when>
+    <when>2010-05-01T13:01:43-05</when>
+    <when>2010-05-01T13:01:48-05</when>
+    <when>2010-05-01T13:01:52-05</when>
+    <when>2010-05-01T13:01:57-05</when>
+    <when>2010-05-01T13:02:02-05</when>
+    <when>2010-05-01T13:02:06-05</when>
+    <when>2010-05-01T13:02:11-05</when>
+    <when>2010-05-01T13:02:16-05</when>
+    <when>2010-05-01T13:02:20-05</when>
+    <when>2010-05-01T13:02:25-05</when>
+    <when>2010-05-01T13:02:29-05</when>
+    <when>2010-05-01T13:02:34-05</when>
+    <when>2010-05-01T13:02:39-05</when>
+    <when>2010-05-01T13:02:43-05</when>
+    <when>2010-05-01T13:02:48-05</when>
+    <when>2010-05-01T13:02:53-05</when>
+    <when>2010-05-01T13:02:57-05</when>
+    <when>2010-05-01T13:03:02-05</when>
+    <when>2010-05-01T13:03:07-05</when>
+    <when>2010-05-01T13:03:11-05</when>
+    <when>2010-05-01T13:03:16-05</when>
+    <when>2010-05-01T13:03:21-05</when>
+    <when>2010-05-01T13:03:25-05</when>
+    <when>2010-05-01T13:03:30-05</when>
+    <when>2010-05-01T13:03:34-05</when>
+    <when>2010-05-01T13:03:39-05</when>
+    <when>2010-05-01T13:03:44-05</when>
+    <when>2010-05-01T13:03:48-05</when>
+    <when>2010-05-01T13:03:53-05</when>
+    <when>2010-05-01T13:03:58-05</when>
+    <when>2010-05-01T13:04:02-05</when>
+    <when>2010-05-01T13:04:07-05</when>
+    <when>2010-05-01T13:04:11-05</when>
+    <when>2010-05-01T13:04:16-05</when>
+    <when>2010-05-01T13:04:21-05</when>
+    <when>2010-05-01T13:04:25-05</when>
+    <when>2010-05-01T13:04:30-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:39-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.5727580977974 45.0236058844647 2530</gx:coord>
+    <gx:coord>-92.5742776202954 45.0237913896498 2530</gx:coord>
+    <gx:coord>-92.5803397933112 45.0241784662561 2499</gx:coord>
+    <gx:coord>-92.5865075192046 45.0247891381303 2469</gx:coord>
+    <gx:coord>-92.5926877928765 45.0257073410966 2469</gx:coord>
+    <gx:coord>-92.5986546763805 45.0261844476041 2438</gx:coord>
+    <gx:coord>-92.6046737535477 45.0267206733977 2438</gx:coord>
+    <gx:coord>-92.6106885874739 45.0275061986719 2438</gx:coord>
+    <gx:coord>-92.616359210337 45.027935793162 2438</gx:coord>
+    <gx:coord>-92.6220735719954 45.028379077688 2438</gx:coord>
+    <gx:coord>-92.6280403097635 45.0290552550566 2438</gx:coord>
+    <gx:coord>-92.6341725652711 45.029824064212 2438</gx:coord>
+    <gx:coord>-92.640279209769 45.0304963952702 2438</gx:coord>
+    <gx:coord>-92.6463747377703 45.0311129317319 2438</gx:coord>
+    <gx:coord>-92.6524891739589 45.0317396965059 2438</gx:coord>
+    <gx:coord>-92.6587083612282 45.0325526597288 2438</gx:coord>
+    <gx:coord>-92.6649573988971 45.0334560566121 2438</gx:coord>
+    <gx:coord>-92.6712436344147 45.0343516389227 2438</gx:coord>
+    <gx:coord>-92.6777900587447 45.0353199754833 2438</gx:coord>
+    <gx:coord>-92.6842020644974 45.0361081217423 2438</gx:coord>
+    <gx:coord>-92.6904510353584 45.0368379981793 2438</gx:coord>
+    <gx:coord>-92.6968618406938 45.0376828531019 2438</gx:coord>
+    <gx:coord>-92.7033318031208 45.0383078021685 2438</gx:coord>
+    <gx:coord>-92.709766951172 45.0386241893014 2438</gx:coord>
+    <gx:coord>-92.7161769864286 45.0390317903939 2438</gx:coord>
+    <gx:coord>-92.7225665589756 45.0396570251316 2408</gx:coord>
+    <gx:coord>-92.7288886541216 45.0403373286575 2438</gx:coord>
+    <gx:coord>-92.7352120601109 45.0409943934305 2438</gx:coord>
+    <gx:coord>-92.7414745561156 45.0416276553236 2438</gx:coord>
+    <gx:coord>-92.7477923122779 45.0424046535325 2438</gx:coord>
+    <gx:coord>-92.7541218465412 45.0434006217761 2438</gx:coord>
+    <gx:coord>-92.7601214481636 45.0440713086474 2438</gx:coord>
+    <gx:coord>-92.7660333478225 45.0444426749968 2438</gx:coord>
+    <gx:coord>-92.772102853148 45.0448779180664 2438</gx:coord>
+    <gx:coord>-92.7780236703859 45.0449122731228 2408</gx:coord>
+    <gx:coord>-92.7839974197715 45.0449532357526 2408</gx:coord>
+    <gx:coord>-92.7902562936361 45.0450709796934 2377</gx:coord>
+    <gx:coord>-92.7962688995386 45.0448540267375 2347</gx:coord>
+    <gx:coord>-92.8024120242439 45.0448640459334 2316</gx:coord>
+    <gx:coord>-92.8087530574681 45.0449050506622 2316</gx:coord>
+    <gx:coord>-92.814709697375 45.0446514037676 2286</gx:coord>
+    <gx:coord>-92.8205575663732 45.0444101119805 2255</gx:coord>
+    <gx:coord>-92.8266048584444 45.0442428819735 2225</gx:coord>
+    <gx:coord>-92.8327618067112 45.0440942522516 2194</gx:coord>
+    <gx:coord>-92.83872651911 45.0438644076684 2164</gx:coord>
+    <gx:coord>-92.8446994303267 45.043730942658 2133</gx:coord>
+    <gx:coord>-92.8506627055935 45.0435520713609 2103</gx:coord>
+    <gx:coord>-92.8563938230908 45.0431897062426 2072</gx:coord>
+    <gx:coord>-92.8622525737075 45.0428768437665 2042</gx:coord>
+    <gx:coord>-92.8680590561999 45.0424504399663 2011</gx:coord>
+    <gx:coord>-92.8739470985612 45.0422191353343 1981</gx:coord>
+    <gx:coord>-92.879905503922 45.0421676833604 1950</gx:coord>
+    <gx:coord>-92.8859780438424 45.0420919545536 1920</gx:coord>
+    <gx:coord>-92.8920993846605 45.0419574098772 1889</gx:coord>
+    <gx:coord>-92.8980850189767 45.041613347859 1859</gx:coord>
+    <gx:coord>-92.9042733870782 45.041256341571 1828</gx:coord>
+    <gx:coord>-92.9105676382912 45.0409944306292 1798</gx:coord>
+    <gx:coord>-92.9169019856279 45.0406669834687 1768</gx:coord>
+    <gx:coord>-92.9233572619921 45.0402533884047 1737</gx:coord>
+    <gx:coord>-92.9301295670095 45.0401453351324 1707</gx:coord>
+    <gx:coord>-92.9368012064813 45.0400078656145 1676</gx:coord>
+    <gx:coord>-92.943436221178 45.0397167044808 1646</gx:coord>
+    <gx:coord>-92.9503058450392 45.0396542676205 1615</gx:coord>
+    <gx:coord>-92.9570389363135 45.0394266771585 1585</gx:coord>
+    <gx:coord>-92.9637736326563 45.0390859598898 1554</gx:coord>
+    <gx:coord>-92.9705134597343 45.0387846980464 1524</gx:coord>
+    <gx:coord>-92.973755360354 45.0384258824988 1508.5</gx:coord>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <speed>235</speed>
+    <speed>246</speed>
+    <speed>239</speed>
+    <speed>244</speed>
+    <speed>234</speed>
+    <speed>232</speed>
+    <speed>238</speed>
+    <speed>227</speed>
+    <speed>228</speed>
+    <speed>229</speed>
+    <speed>229</speed>
+    <speed>232</speed>
+    <speed>236</speed>
+    <speed>238</speed>
+    <speed>249</speed>
+    <speed>243</speed>
+    <speed>245</speed>
+    <speed>255</speed>
+    <speed>247</speed>
+    <speed>248</speed>
+    <speed>248</speed>
+    <speed>247</speed>
+    <speed>256</speed>
+    <speed>247</speed>
+    <speed>246</speed>
+    <speed>254</speed>
+    <speed>244</speed>
+    <speed>245</speed>
+    <speed>242</speed>
+    <speed>239</speed>
+    <speed>246</speed>
+    <speed>235</speed>
+    <speed>232</speed>
+    <speed>240</speed>
+    <speed>231</speed>
+    <speed>232</speed>
+    <speed>234</speed>
+    <speed>234</speed>
+    <speed>233</speed>
+    <speed>232</speed>
+    <speed>233</speed>
+    <speed>232</speed>
+    <speed>229</speed>
+    <speed>229</speed>
+    <speed>237</speed>
+    <speed>227</speed>
+    <speed>225</speed>
+    <speed>233</speed>
+    <speed>224</speed>
+    <speed>225</speed>
+    <speed>228</speed>
+    <speed>228</speed>
+    <speed>240</speed>
+    <speed>233</speed>
+    <speed>236</speed>
+    <speed>248</speed>
+    <speed>243</speed>
+    <speed>246</speed>
+    <speed>250</speed>
+    <speed>253</speed>
+    <speed>255</speed>
+    <speed>257</speed>
+    <speed>257</speed>
+    <speed>266</speed>
+    <speed>261</speed>
+    <speed>265</speed>
+    <speed>275</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>CPZ5695</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:25-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:02-05</when>
+    <when>2010-05-01T13:01:06-05</when>
+    <when>2010-05-01T13:01:11-05</when>
+    <when>2010-05-01T13:01:16-05</when>
+    <when>2010-05-01T13:01:20-05</when>
+    <when>2010-05-01T13:01:25-05</when>
+    <when>2010-05-01T13:01:29-05</when>
+    <when>2010-05-01T13:01:34-05</when>
+    <when>2010-05-01T13:01:39-05</when>
+    <when>2010-05-01T13:01:43-05</when>
+    <when>2010-05-01T13:01:48-05</when>
+    <when>2010-05-01T13:01:53-05</when>
+    <when>2010-05-01T13:01:57-05</when>
+    <when>2010-05-01T13:02:02-05</when>
+    <when>2010-05-01T13:02:06-05</when>
+    <when>2010-05-01T13:02:11-05</when>
+    <when>2010-05-01T13:02:16-05</when>
+    <when>2010-05-01T13:02:20-05</when>
+    <when>2010-05-01T13:02:25-05</when>
+    <when>2010-05-01T13:02:30-05</when>
+    <when>2010-05-01T13:02:34-05</when>
+    <when>2010-05-01T13:02:39-05</when>
+    <when>2010-05-01T13:02:44-05</when>
+    <when>2010-05-01T13:02:48-05</when>
+    <when>2010-05-01T13:02:53-05</when>
+    <when>2010-05-01T13:02:58-05</when>
+    <when>2010-05-01T13:03:02-05</when>
+    <when>2010-05-01T13:03:07-05</when>
+    <when>2010-05-01T13:03:11-05</when>
+    <when>2010-05-01T13:03:16-05</when>
+    <when>2010-05-01T13:03:21-05</when>
+    <when>2010-05-01T13:03:25-05</when>
+    <when>2010-05-01T13:03:30-05</when>
+    <when>2010-05-01T13:03:35-05</when>
+    <when>2010-05-01T13:03:39-05</when>
+    <when>2010-05-01T13:03:44-05</when>
+    <when>2010-05-01T13:03:48-05</when>
+    <when>2010-05-01T13:03:53-05</when>
+    <when>2010-05-01T13:03:58-05</when>
+    <when>2010-05-01T13:04:02-05</when>
+    <when>2010-05-01T13:04:07-05</when>
+    <when>2010-05-01T13:04:12-05</when>
+    <when>2010-05-01T13:04:16-05</when>
+    <when>2010-05-01T13:04:21-05</when>
+    <when>2010-05-01T13:04:25-05</when>
+    <when>2010-05-01T13:04:30-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:39-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.3689380245182 45.0389467469425 2804</gx:coord>
+    <gx:coord>-92.3759530819834 45.0380951007958 2773</gx:coord>
+    <gx:coord>-92.3831159633175 45.0369957486846 2712</gx:coord>
+    <gx:coord>-92.3901362714549 45.0355238496347 2651</gx:coord>
+    <gx:coord>-92.3970814910858 45.0339385808083 2621</gx:coord>
+    <gx:coord>-92.4043121546626 45.032585906621 2560</gx:coord>
+    <gx:coord>-92.4118367565321 45.0319048652958 2499</gx:coord>
+    <gx:coord>-92.419078934653 45.030875157485 2469</gx:coord>
+    <gx:coord>-92.4262095560369 45.0291153314744 2438</gx:coord>
+    <gx:coord>-92.4335237384463 45.0273941113051 2438</gx:coord>
+    <gx:coord>-92.4408178608932 45.0260076351757 2438</gx:coord>
+    <gx:coord>-92.4480506692593 45.0250407396261 2438</gx:coord>
+    <gx:coord>-92.4553504288427 45.0241919539362 2438</gx:coord>
+    <gx:coord>-92.4628196268122 45.0233514202756 2438</gx:coord>
+    <gx:coord>-92.4702544151504 45.0225228770055 2438</gx:coord>
+    <gx:coord>-92.47749082249 45.0211454469826 2438</gx:coord>
+    <gx:coord>-92.4849952170224 45.020108381381 2438</gx:coord>
+    <gx:coord>-92.4924975545976 45.0191930140492 2438</gx:coord>
+    <gx:coord>-92.4998773018653 45.018051767506 2438</gx:coord>
+    <gx:coord>-92.507186344501 45.0168407571941 2438</gx:coord>
+    <gx:coord>-92.5143825240876 45.0156216694574 2438</gx:coord>
+    <gx:coord>-92.5215706342598 45.0143945866018 2438</gx:coord>
+    <gx:coord>-92.5287558465591 45.0131646175633 2408</gx:coord>
+    <gx:coord>-92.535858877656 45.0118804989009 2438</gx:coord>
+    <gx:coord>-92.5428413996463 45.0103972607613 2438</gx:coord>
+    <gx:coord>-92.5499799537839 45.0091469907013 2438</gx:coord>
+    <gx:coord>-92.5571487214372 45.0079107943641 2438</gx:coord>
+    <gx:coord>-92.5643503087637 45.0069312146329 2438</gx:coord>
+    <gx:coord>-92.5715906639656 45.0060256188488 2438</gx:coord>
+    <gx:coord>-92.5787232800865 45.0051593960756 2438</gx:coord>
+    <gx:coord>-92.5859075456731 45.0042853983707 2438</gx:coord>
+    <gx:coord>-92.5932558590921 45.0033774426771 2438</gx:coord>
+    <gx:coord>-92.6008071462461 45.003154553905 2438</gx:coord>
+    <gx:coord>-92.6083537686074 45.0033879703399 2438</gx:coord>
+    <gx:coord>-92.6158581079963 45.0039900406543 2438</gx:coord>
+    <gx:coord>-92.6233760961899 45.0046768119547 2438</gx:coord>
+    <gx:coord>-92.6308149850999 45.0051419435105 2438</gx:coord>
+    <gx:coord>-92.6382172211892 45.0057401438498 2438</gx:coord>
+    <gx:coord>-92.6454696132537 45.005920412465 2438</gx:coord>
+    <gx:coord>-92.6528385211424 45.0061349890872 2438</gx:coord>
+    <gx:coord>-92.6604262143734 45.0071927884136 2438</gx:coord>
+    <gx:coord>-92.6679454156809 45.0082888895876 2438</gx:coord>
+    <gx:coord>-92.6753888547959 45.008928558351 2438</gx:coord>
+    <gx:coord>-92.6828869677601 45.0095857895273 2438</gx:coord>
+    <gx:coord>-92.6904366005728 45.0101503984089 2438</gx:coord>
+    <gx:coord>-92.6979032678841 45.0107232636276 2438</gx:coord>
+    <gx:coord>-92.7052708180676 45.0115414340457 2438</gx:coord>
+    <gx:coord>-92.7127263858549 45.0123186978698 2438</gx:coord>
+    <gx:coord>-92.7203010090271 45.0129672732945 2438</gx:coord>
+    <gx:coord>-92.7279385048165 45.0135255760157 2438</gx:coord>
+    <gx:coord>-92.7356653752599 45.0142972080147 2438</gx:coord>
+    <gx:coord>-92.7433569853567 45.0149059605824 2438</gx:coord>
+    <gx:coord>-92.7510393079923 45.0155634422272 2438</gx:coord>
+    <gx:coord>-92.7586012608679 45.0164147107502 2438</gx:coord>
+    <gx:coord>-92.7660563085583 45.0171035403725 2438</gx:coord>
+    <gx:coord>-92.7735654020359 45.0178109394289 2408</gx:coord>
+    <gx:coord>-92.7808966683949 45.0181973511467 2347</gx:coord>
+    <gx:coord>-92.7882227912656 45.0186079478789 2316</gx:coord>
+    <gx:coord>-92.7955583985804 45.0193002290468 2255</gx:coord>
+    <gx:coord>-92.802877137723 45.0198997944223 2194</gx:coord>
+    <gx:coord>-92.810330496953 45.0205558578153 2164</gx:coord>
+    <gx:coord>-92.8178805010647 45.0213805814075 2103</gx:coord>
+    <gx:coord>-92.8253364059255 45.0220160857506 2072</gx:coord>
+    <gx:coord>-92.8282952283228 45.0222965993536 2047.6</gx:coord>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <speed>277</speed>
+    <speed>288</speed>
+    <speed>283</speed>
+    <speed>291</speed>
+    <speed>283</speed>
+    <speed>284</speed>
+    <speed>298</speed>
+    <speed>288</speed>
+    <speed>288</speed>
+    <speed>286</speed>
+    <speed>287</speed>
+    <speed>287</speed>
+    <speed>286</speed>
+    <speed>286</speed>
+    <speed>299</speed>
+    <speed>289</speed>
+    <speed>289</speed>
+    <speed>299</speed>
+    <speed>287</speed>
+    <speed>286</speed>
+    <speed>284</speed>
+    <speed>282</speed>
+    <speed>292</speed>
+    <speed>281</speed>
+    <speed>281</speed>
+    <speed>291</speed>
+    <speed>280</speed>
+    <speed>280</speed>
+    <speed>281</speed>
+    <speed>282</speed>
+    <speed>283</speed>
+    <speed>284</speed>
+    <speed>286</speed>
+    <speed>287</speed>
+    <speed>287</speed>
+    <speed>286</speed>
+    <speed>295</speed>
+    <speed>285</speed>
+    <speed>286</speed>
+    <speed>297</speed>
+    <speed>287</speed>
+    <speed>289</speed>
+    <speed>290</speed>
+    <speed>288</speed>
+    <speed>298</speed>
+    <speed>288</speed>
+    <speed>289</speed>
+    <speed>302</speed>
+    <speed>292</speed>
+    <speed>294</speed>
+    <speed>294</speed>
+    <speed>294</speed>
+    <speed>304</speed>
+    <speed>290</speed>
+    <speed>288</speed>
+    <speed>297</speed>
+    <speed>284</speed>
+    <speed>284</speed>
+    <speed>284</speed>
+    <speed>285</speed>
+    <speed>286</speed>
+    <speed>278</speed>
+    <speed>282</speed>
+    <speed>288</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>DC95</name>
+  <adflag>A</adflag>
+  <flightid>DAL2858</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:03-05</when>
+    <when>2010-05-01T13:00:07-05</when>
+    <when>2010-05-01T13:00:12-05</when>
+    <when>2010-05-01T13:00:17-05</when>
+    <when>2010-05-01T13:00:21-05</when>
+    <when>2010-05-01T13:00:26-05</when>
+    <when>2010-05-01T13:00:30-05</when>
+    <when>2010-05-01T13:00:35-05</when>
+    <when>2010-05-01T13:00:40-05</when>
+    <when>2010-05-01T13:00:44-05</when>
+    <when>2010-05-01T13:00:49-05</when>
+    <when>2010-05-01T13:00:54-05</when>
+    <when>2010-05-01T13:00:58-05</when>
+    <when>2010-05-01T13:01:03-05</when>
+    <when>2010-05-01T13:01:07-05</when>
+    <when>2010-05-01T13:01:12-05</when>
+    <when>2010-05-01T13:01:17-05</when>
+    <when>2010-05-01T13:01:21-05</when>
+    <when>2010-05-01T13:01:26-05</when>
+    <when>2010-05-01T13:01:31-05</when>
+    <when>2010-05-01T13:01:35-05</when>
+    <when>2010-05-01T13:01:40-05</when>
+    <when>2010-05-01T13:01:45-05</when>
+    <when>2010-05-01T13:01:49-05</when>
+    <when>2010-05-01T13:01:54-05</when>
+    <when>2010-05-01T13:01:58-05</when>
+    <when>2010-05-01T13:02:03-05</when>
+    <when>2010-05-01T13:02:08-05</when>
+    <when>2010-05-01T13:02:12-05</when>
+    <when>2010-05-01T13:02:17-05</when>
+    <when>2010-05-01T13:02:22-05</when>
+    <when>2010-05-01T13:02:26-05</when>
+    <when>2010-05-01T13:02:31-05</when>
+    <when>2010-05-01T13:02:35-05</when>
+    <when>2010-05-01T13:02:40-05</when>
+    <when>2010-05-01T13:02:45-05</when>
+    <when>2010-05-01T13:02:49-05</when>
+    <when>2010-05-01T13:02:54-05</when>
+    <when>2010-05-01T13:02:59-05</when>
+    <when>2010-05-01T13:03:03-05</when>
+    <when>2010-05-01T13:03:08-05</when>
+    <when>2010-05-01T13:03:12-05</when>
+    <when>2010-05-01T13:03:17-05</when>
+    <when>2010-05-01T13:03:22-05</when>
+    <when>2010-05-01T13:03:26-05</when>
+    <when>2010-05-01T13:03:31-05</when>
+    <when>2010-05-01T13:03:36-05</when>
+    <when>2010-05-01T13:03:40-05</when>
+    <when>2010-05-01T13:03:45-05</when>
+    <when>2010-05-01T13:03:49-05</when>
+    <when>2010-05-01T13:03:54-05</when>
+    <when>2010-05-01T13:03:59-05</when>
+    <when>2010-05-01T13:04:03-05</when>
+    <when>2010-05-01T13:04:08-05</when>
+    <when>2010-05-01T13:04:12-05</when>
+    <when>2010-05-01T13:04:17-05</when>
+    <when>2010-05-01T13:04:22-05</when>
+    <when>2010-05-01T13:04:26-05</when>
+    <when>2010-05-01T13:04:31-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:40-05</when>
+    <when>2010-05-01T13:04:45-05</when>
+    <when>2010-05-01T13:04:50-05</when>
+    <when>2010-05-01T13:04:54-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.1962465696187 44.4584257162471 3078</gx:coord>
+    <gx:coord>-93.1954858158128 44.462643897726 3078</gx:coord>
+    <gx:coord>-93.1945524569257 44.4696206853623 3048</gx:coord>
+    <gx:coord>-93.1935347734104 44.4765680167011 3048</gx:coord>
+    <gx:coord>-93.1921548885013 44.4834366892852 3048</gx:coord>
+    <gx:coord>-93.1912787899895 44.4902740201102 3048</gx:coord>
+    <gx:coord>-93.190869393024 44.496999598511 3048</gx:coord>
+    <gx:coord>-93.190355669541 44.503701889363 3048</gx:coord>
+    <gx:coord>-93.1899042890233 44.510392533924 3048</gx:coord>
+    <gx:coord>-93.1894352972433 44.5171043633827 3048</gx:coord>
+    <gx:coord>-93.1887272976791 44.523838031578 3017</gx:coord>
+    <gx:coord>-93.1882343860587 44.5305421014878 2987</gx:coord>
+    <gx:coord>-93.1878483537445 44.5373007218153 2987</gx:coord>
+    <gx:coord>-93.187206305476 44.5440099500882 2956</gx:coord>
+    <gx:coord>-93.1868272718258 44.5507044137326 2956</gx:coord>
+    <gx:coord>-93.1868012917709 44.5573772972405 2926</gx:coord>
+    <gx:coord>-93.1866210269778 44.5640837167977 2895</gx:coord>
+    <gx:coord>-93.1864907616916 44.5708828364002 2865</gx:coord>
+    <gx:coord>-93.1863883659992 44.5775823065512 2865</gx:coord>
+    <gx:coord>-93.1863783383684 44.5842436541366 2834</gx:coord>
+    <gx:coord>-93.1864309457268 44.5909344741626 2804</gx:coord>
+    <gx:coord>-93.1861870344 44.5974636699094 2804</gx:coord>
+    <gx:coord>-93.1859399656477 44.6039556552385 2804</gx:coord>
+    <gx:coord>-93.1853781106637 44.6104625660741 2773</gx:coord>
+    <gx:coord>-93.1842558921345 44.6168860904061 2743</gx:coord>
+    <gx:coord>-93.1824878787618 44.6232658876223 2712</gx:coord>
+    <gx:coord>-93.1803879773166 44.6294813300019 2743</gx:coord>
+    <gx:coord>-93.1780367881352 44.6355848757922 2743</gx:coord>
+    <gx:coord>-93.1752316985335 44.6415358145216 2743</gx:coord>
+    <gx:coord>-93.1723853204738 44.6473610477966 2743</gx:coord>
+    <gx:coord>-93.1695650439908 44.6531642714264 2743</gx:coord>
+    <gx:coord>-93.1665274417428 44.6589294401132 2743</gx:coord>
+    <gx:coord>-93.163312582578 44.6647085135481 2743</gx:coord>
+    <gx:coord>-93.160128277284 44.6704265732562 2743</gx:coord>
+    <gx:coord>-93.1572001510497 44.6760520191633 2743</gx:coord>
+    <gx:coord>-93.1543945309268 44.6816953047965 2743</gx:coord>
+    <gx:coord>-93.1513717350775 44.6874085817504 2743</gx:coord>
+    <gx:coord>-93.148373004873 44.693058643812 2743</gx:coord>
+    <gx:coord>-93.1453860883093 44.6986645847547 2743</gx:coord>
+    <gx:coord>-93.1421804531017 44.7042897996493 2743</gx:coord>
+    <gx:coord>-93.1388918899721 44.7099624804852 2743</gx:coord>
+    <gx:coord>-93.1358117624936 44.7156532681924 2743</gx:coord>
+    <gx:coord>-93.1330575833882 44.7212682920708 2743</gx:coord>
+    <gx:coord>-93.1302162164891 44.7268585149398 2743</gx:coord>
+    <gx:coord>-93.1271891227658 44.7324687008066 2743</gx:coord>
+    <gx:coord>-93.1242151781308 44.7380337584283 2743</gx:coord>
+    <gx:coord>-93.1211166531293 44.7436002967353 2743</gx:coord>
+    <gx:coord>-93.1178719942563 44.7492107287761 2743</gx:coord>
+    <gx:coord>-93.1146752953943 44.7548599499827 2743</gx:coord>
+    <gx:coord>-93.1117422413574 44.7605559725452 2743</gx:coord>
+    <gx:coord>-93.1091424380409 44.7663214899376 2743</gx:coord>
+    <gx:coord>-93.1066566399229 44.7720715320148 2743</gx:coord>
+    <gx:coord>-93.1040152138285 44.7778692510771 2743</gx:coord>
+    <gx:coord>-93.1012154435684 44.7836013270224 2743</gx:coord>
+    <gx:coord>-93.0982479017436 44.7892173348525 2743</gx:coord>
+    <gx:coord>-93.0950640890821 44.7947430846626 2743</gx:coord>
+    <gx:coord>-93.0915034480367 44.800094039287 2743</gx:coord>
+    <gx:coord>-93.0873387008124 44.8052382540424 2743</gx:coord>
+    <gx:coord>-93.0825976468131 44.8101709774442 2743</gx:coord>
+    <gx:coord>-93.0776830792116 44.815032321238 2773</gx:coord>
+    <gx:coord>-93.0728317182526 44.8197880022073 2773</gx:coord>
+    <gx:coord>-93.0680578728105 44.8244689148117 2773</gx:coord>
+    <gx:coord>-93.0633853777291 44.829181080911 2743</gx:coord>
+    <gx:coord>-93.0589797309512 44.8338258031244 2743</gx:coord>
+    <gx:coord>-93.0546552480593 44.8384413086509 2743</gx:coord>
+    <gx:coord>-93.0501805533684 44.8430463359799 2743</gx:coord>
+    <gx:coord>-93.0484252769533 44.8448678241347 2743</gx:coord>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>40 0 0</gx:angles>
+    <gx:angles>40 0 0</gx:angles>
+    <gx:angles>40 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <gx:angles>30 0 0</gx:angles>
+    <speed>378</speed>
+    <speed>370</speed>
+    <speed>381</speed>
+    <speed>373</speed>
+    <speed>384</speed>
+    <speed>367</speed>
+    <speed>365</speed>
+    <speed>377</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>376</speed>
+    <speed>361</speed>
+    <speed>362</speed>
+    <speed>375</speed>
+    <speed>361</speed>
+    <speed>361</speed>
+    <speed>359</speed>
+    <speed>358</speed>
+    <speed>355</speed>
+    <speed>353</speed>
+    <speed>352</speed>
+    <speed>362</speed>
+    <speed>347</speed>
+    <speed>346</speed>
+    <speed>355</speed>
+    <speed>339</speed>
+    <speed>336</speed>
+    <speed>335</speed>
+    <speed>333</speed>
+    <speed>343</speed>
+    <speed>329</speed>
+    <speed>329</speed>
+    <speed>340</speed>
+    <speed>325</speed>
+    <speed>325</speed>
+    <speed>326</speed>
+    <speed>327</speed>
+    <speed>338</speed>
+    <speed>325</speed>
+    <speed>325</speed>
+    <speed>336</speed>
+    <speed>322</speed>
+    <speed>322</speed>
+    <speed>324</speed>
+    <speed>325</speed>
+    <speed>338</speed>
+    <speed>326</speed>
+    <speed>327</speed>
+    <speed>339</speed>
+    <speed>326</speed>
+    <speed>337</speed>
+    <speed>324</speed>
+    <speed>323</speed>
+    <speed>334</speed>
+    <speed>321</speed>
+    <speed>332</speed>
+    <speed>318</speed>
+    <speed>317</speed>
+    <speed>314</speed>
+    <speed>310</speed>
+    <speed>318</speed>
+    <speed>303</speed>
+    <speed>306</speed>
+    <speed>311</speed>
+    <speed>322</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>B737</name>
+  <adflag>A</adflag>
+  <flightid>SWA1488</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:01-05</when>
+    <when>2010-05-01T13:01:06-05</when>
+    <when>2010-05-01T13:01:11-05</when>
+    <when>2010-05-01T13:01:15-05</when>
+    <when>2010-05-01T13:01:20-05</when>
+    <when>2010-05-01T13:01:25-05</when>
+    <when>2010-05-01T13:01:29-05</when>
+    <when>2010-05-01T13:01:34-05</when>
+    <when>2010-05-01T13:01:38-05</when>
+    <when>2010-05-01T13:01:43-05</when>
+    <when>2010-05-01T13:01:48-05</when>
+    <when>2010-05-01T13:01:52-05</when>
+    <when>2010-05-01T13:01:57-05</when>
+    <when>2010-05-01T13:02:02-05</when>
+    <when>2010-05-01T13:02:06-05</when>
+    <when>2010-05-01T13:02:11-05</when>
+    <when>2010-05-01T13:02:15-05</when>
+    <when>2010-05-01T13:02:20-05</when>
+    <when>2010-05-01T13:02:25-05</when>
+    <when>2010-05-01T13:02:29-05</when>
+    <when>2010-05-01T13:02:34-05</when>
+    <when>2010-05-01T13:02:39-05</when>
+    <when>2010-05-01T13:02:43-05</when>
+    <when>2010-05-01T13:02:48-05</when>
+    <when>2010-05-01T13:02:53-05</when>
+    <when>2010-05-01T13:02:57-05</when>
+    <when>2010-05-01T13:03:02-05</when>
+    <when>2010-05-01T13:03:06-05</when>
+    <when>2010-05-01T13:03:11-05</when>
+    <when>2010-05-01T13:03:16-05</when>
+    <when>2010-05-01T13:03:20-05</when>
+    <when>2010-05-01T13:03:25-05</when>
+    <when>2010-05-01T13:03:30-05</when>
+    <when>2010-05-01T13:03:34-05</when>
+    <when>2010-05-01T13:03:39-05</when>
+    <when>2010-05-01T13:03:44-05</when>
+    <when>2010-05-01T13:03:48-05</when>
+    <when>2010-05-01T13:03:53-05</when>
+    <when>2010-05-01T13:03:57-05</when>
+    <when>2010-05-01T13:04:02-05</when>
+    <when>2010-05-01T13:04:07-05</when>
+    <when>2010-05-01T13:04:11-05</when>
+    <when>2010-05-01T13:04:16-05</when>
+    <when>2010-05-01T13:04:21-05</when>
+    <when>2010-05-01T13:04:25-05</when>
+    <when>2010-05-01T13:04:30-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:39-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.7436038977339 45.0176449723009 2438</gx:coord>
+    <gx:coord>-92.745419752639 45.0178405701636 2438</gx:coord>
+    <gx:coord>-92.7525586927583 45.0181852080204 2438</gx:coord>
+    <gx:coord>-92.7599978682742 45.0189437491361 2438</gx:coord>
+    <gx:coord>-92.7673964649616 45.0200176804669 2438</gx:coord>
+    <gx:coord>-92.7743047878147 45.0206512321095 2438</gx:coord>
+    <gx:coord>-92.7812211106102 45.0212438545962 2438</gx:coord>
+    <gx:coord>-92.7880905786106 45.0219352711124 2438</gx:coord>
+    <gx:coord>-92.7948110303679 45.0225135550872 2438</gx:coord>
+    <gx:coord>-92.8016256231407 45.0231539091809 2377</gx:coord>
+    <gx:coord>-92.808436321378 45.0237782407713 2316</gx:coord>
+    <gx:coord>-92.8153060032773 45.0245123996427 2255</gx:coord>
+    <gx:coord>-92.8220950756464 45.0250388052127 2194</gx:coord>
+    <gx:coord>-92.8289929014999 45.0256725515916 2164</gx:coord>
+    <gx:coord>-92.8360303531199 45.0266058986232 2103</gx:coord>
+    <gx:coord>-92.8429329578141 45.0273764305379 2072</gx:coord>
+    <gx:coord>-92.8498901242601 45.0280031718838 2011</gx:coord>
+    <gx:coord>-92.8570769257727 45.0288350738651 1981</gx:coord>
+    <gx:coord>-92.8642468830706 45.0297437485852 1920</gx:coord>
+    <gx:coord>-92.87096733955 45.0302316004222 1859</gx:coord>
+    <gx:coord>-92.8776991433842 45.0308036595577 1828</gx:coord>
+    <gx:coord>-92.8848051869188 45.0317355139572 1768</gx:coord>
+    <gx:coord>-92.891849836226 45.032372254553 1737</gx:coord>
+    <gx:coord>-92.8988806858275 45.0330472653869 1676</gx:coord>
+    <gx:coord>-92.9059183042329 45.0336591058208 1646</gx:coord>
+    <gx:coord>-92.9127864875957 45.0340529790218 1554</gx:coord>
+    <gx:coord>-92.9198394657117 45.0347605723218 1554</gx:coord>
+    <gx:coord>-92.9271188759936 45.0355320490291 1493</gx:coord>
+    <gx:coord>-92.9342496165443 45.0361866089878 1463</gx:coord>
+    <gx:coord>-92.9413321497396 45.0366031935849 1402</gx:coord>
+    <gx:coord>-92.9482307097935 45.0364375819171 1371</gx:coord>
+    <gx:coord>-92.9549267830033 45.0357359075476 1341</gx:coord>
+    <gx:coord>-92.9616308114574 45.0349106615543 1310</gx:coord>
+    <gx:coord>-92.9680840982828 45.0340026299843 1280</gx:coord>
+    <gx:coord>-92.9744518648424 45.0330474137801 1280</gx:coord>
+    <gx:coord>-92.9808447078198 45.0322448064613 1249</gx:coord>
+    <gx:coord>-92.9869393112267 45.0312693675023 1219</gx:coord>
+    <gx:coord>-92.9930579883147 45.0303271096009 1219</gx:coord>
+    <gx:coord>-92.9991883691893 45.0295800716662 1219</gx:coord>
+    <gx:coord>-93.0050223477826 45.028724083281 1219</gx:coord>
+    <gx:coord>-93.010614076045 45.0278629900138 1219</gx:coord>
+    <gx:coord>-93.0160206405037 45.0268346460011 1219</gx:coord>
+    <gx:coord>-93.0211552000865 45.0253145800507 1219</gx:coord>
+    <gx:coord>-93.0258637412524 45.0233023458284 1219</gx:coord>
+    <gx:coord>-93.0300671724338 45.0208133465794 1219</gx:coord>
+    <gx:coord>-93.0339928023023 45.0180815293661 1219</gx:coord>
+    <gx:coord>-93.0378123650471 45.015386905955 1219</gx:coord>
+    <gx:coord>-93.0413573567597 45.0126147468646 1219</gx:coord>
+    <gx:coord>-93.0448863339261 45.0099395682965 1219</gx:coord>
+    <gx:coord>-93.0485234513263 45.0073532174657 1219</gx:coord>
+    <gx:coord>-93.0521310871894 45.0048422081768 1219</gx:coord>
+    <gx:coord>-93.0555350014272 45.0023982293894 1219</gx:coord>
+    <gx:coord>-93.0589786824276 45.0000288885742 1188</gx:coord>
+    <gx:coord>-93.0623077105646 44.9977133640953 1188</gx:coord>
+    <gx:coord>-93.065360230814 44.995356896404 1158</gx:coord>
+    <gx:coord>-93.0685763415021 44.9931569267686 1158</gx:coord>
+    <gx:coord>-93.0718407580212 44.9911674357548 1097</gx:coord>
+    <gx:coord>-93.0748577258473 44.9891037291536 1066</gx:coord>
+    <gx:coord>-93.0778092168993 44.9869633801591 1036</gx:coord>
+    <gx:coord>-93.0808539061589 44.9848563483924 1006</gx:coord>
+    <gx:coord>-93.0836846650629 44.9827278139486 975</gx:coord>
+    <gx:coord>-93.0863847135489 44.9806419407598 945</gx:coord>
+    <gx:coord>-93.0891432094711 44.978586338985 945</gx:coord>
+    <gx:coord>-93.0918882385755 44.9764807737863 945</gx:coord>
+    <gx:coord>-93.0946313764692 44.9743266948072 914</gx:coord>
+    <gx:coord>-93.0974123770403 44.9722534220515 914</gx:coord>
+    <gx:coord>-93.0987847859357 44.9712598545857 899</gx:coord>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>240 0 0</gx:angles>
+    <gx:angles>240 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <speed>280</speed>
+    <speed>293</speed>
+    <speed>284</speed>
+    <speed>288</speed>
+    <speed>274</speed>
+    <speed>272</speed>
+    <speed>279</speed>
+    <speed>263</speed>
+    <speed>263</speed>
+    <speed>262</speed>
+    <speed>262</speed>
+    <speed>275</speed>
+    <speed>266</speed>
+    <speed>267</speed>
+    <speed>279</speed>
+    <speed>272</speed>
+    <speed>271</speed>
+    <speed>268</speed>
+    <speed>269</speed>
+    <speed>280</speed>
+    <speed>269</speed>
+    <speed>267</speed>
+    <speed>278</speed>
+    <speed>270</speed>
+    <speed>271</speed>
+    <speed>272</speed>
+    <speed>272</speed>
+    <speed>281</speed>
+    <speed>270</speed>
+    <speed>268</speed>
+    <speed>273</speed>
+    <speed>259</speed>
+    <speed>255</speed>
+    <speed>250</speed>
+    <speed>247</speed>
+    <speed>244</speed>
+    <speed>239</speed>
+    <speed>235</speed>
+    <speed>238</speed>
+    <speed>224</speed>
+    <speed>220</speed>
+    <speed>224</speed>
+    <speed>212</speed>
+    <speed>210</speed>
+    <speed>208</speed>
+    <speed>206</speed>
+    <speed>204</speed>
+    <speed>200</speed>
+    <speed>197</speed>
+    <speed>200</speed>
+    <speed>189</speed>
+    <speed>185</speed>
+    <speed>188</speed>
+    <speed>176</speed>
+    <speed>172</speed>
+    <speed>168</speed>
+    <speed>165</speed>
+    <speed>163</speed>
+    <speed>159</speed>
+    <speed>158</speed>
+    <speed>157</speed>
+    <speed>156</speed>
+    <speed>155</speed>
+    <speed>159</speed>
+    <speed>156</speed>
+    <speed>160</speed>
+    <speed>165</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>CRJ2</name>
+  <adflag>A</adflag>
+  <flightid>MES3237</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:02:11-05</when>
+    <when>2010-05-01T13:02:16-05</when>
+    <when>2010-05-01T13:02:20-05</when>
+    <when>2010-05-01T13:02:25-05</when>
+    <when>2010-05-01T13:02:30-05</when>
+    <when>2010-05-01T13:02:34-05</when>
+    <when>2010-05-01T13:02:39-05</when>
+    <when>2010-05-01T13:02:44-05</when>
+    <when>2010-05-01T13:02:48-05</when>
+    <when>2010-05-01T13:02:53-05</when>
+    <when>2010-05-01T13:02:58-05</when>
+    <when>2010-05-01T13:03:02-05</when>
+    <when>2010-05-01T13:03:07-05</when>
+    <when>2010-05-01T13:03:11-05</when>
+    <when>2010-05-01T13:03:16-05</when>
+    <when>2010-05-01T13:03:21-05</when>
+    <when>2010-05-01T13:03:25-05</when>
+    <when>2010-05-01T13:03:30-05</when>
+    <when>2010-05-01T13:03:35-05</when>
+    <when>2010-05-01T13:03:39-05</when>
+    <when>2010-05-01T13:03:44-05</when>
+    <when>2010-05-01T13:03:49-05</when>
+    <when>2010-05-01T13:03:53-05</when>
+    <when>2010-05-01T13:03:58-05</when>
+    <when>2010-05-01T13:04:02-05</when>
+    <when>2010-05-01T13:04:07-05</when>
+    <when>2010-05-01T13:04:12-05</when>
+    <when>2010-05-01T13:04:16-05</when>
+    <when>2010-05-01T13:04:21-05</when>
+    <when>2010-05-01T13:04:26-05</when>
+    <when>2010-05-01T13:04:30-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:39-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.3654525809466 45.0395326832503 2865</gx:coord>
+    <gx:coord>-92.3722148453194 45.0383957360594 2804</gx:coord>
+    <gx:coord>-92.3789968405533 45.0372550297716 2743</gx:coord>
+    <gx:coord>-92.3857717937338 45.035790850493 2712</gx:coord>
+    <gx:coord>-92.3928268643983 45.0344988210948 2651</gx:coord>
+    <gx:coord>-92.4001469312933 45.033871851974 2560</gx:coord>
+    <gx:coord>-92.4074037761026 45.0334790794383 2530</gx:coord>
+    <gx:coord>-92.4143764863149 45.0325702739764 2469</gx:coord>
+    <gx:coord>-92.4212444848282 45.0311814951256 2438</gx:coord>
+    <gx:coord>-92.4279010170141 45.0296690432212 2438</gx:coord>
+    <gx:coord>-92.4345565361906 45.0284146419212 2438</gx:coord>
+    <gx:coord>-92.4413302267182 45.0272251811423 2438</gx:coord>
+    <gx:coord>-92.4480836488953 45.0260669070124 2438</gx:coord>
+    <gx:coord>-92.4551038107528 45.0251701649012 2438</gx:coord>
+    <gx:coord>-92.4620867595928 45.0240801934066 2469</gx:coord>
+    <gx:coord>-92.4688445943801 45.0226696219111 2438</gx:coord>
+    <gx:coord>-92.475770828578 45.0214068742927 2438</gx:coord>
+    <gx:coord>-92.4828770275976 45.0207461539528 2438</gx:coord>
+    <gx:coord>-92.4898573176066 45.0197355515252 2438</gx:coord>
+    <gx:coord>-92.4967644710332 45.0183323474054 2438</gx:coord>
+    <gx:coord>-92.5037089663701 45.0170733409348 2438</gx:coord>
+    <gx:coord>-92.5107248421742 45.0161283120616 2438</gx:coord>
+    <gx:coord>-92.5176434168212 45.0153021033734 2438</gx:coord>
+    <gx:coord>-92.5246160799064 45.014766408047 2438</gx:coord>
+    <gx:coord>-92.5318394590384 45.0148138551787 2438</gx:coord>
+    <gx:coord>-92.5390862704917 45.0145094336569 2438</gx:coord>
+    <gx:coord>-92.5463963852328 45.0143318745824 2438</gx:coord>
+    <gx:coord>-92.5536631015454 45.0147147936455 2438</gx:coord>
+    <gx:coord>-92.5607664550331 45.014765244052 2438</gx:coord>
+    <gx:coord>-92.5679894227165 45.0149152572076 2438</gx:coord>
+    <gx:coord>-92.5752195833593 45.0150827900687 2438</gx:coord>
+    <gx:coord>-92.582448917158 45.015235432103 2438</gx:coord>
+    <gx:coord>-92.5897932283758 45.0155897891663 2438</gx:coord>
+    <gx:coord>-92.5970842773637 45.0160017913126 2438</gx:coord>
+    <gx:coord>-92.6042355431238 45.0161855996339 2438</gx:coord>
+    <gx:coord>-92.6114545174405 45.0162505274554 2438</gx:coord>
+    <gx:coord>-92.6187520939916 45.0164837409472 2438</gx:coord>
+    <gx:coord>-92.6216565981247 45.0165937676212 2438</gx:coord>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <speed>267</speed>
+    <speed>265</speed>
+    <speed>277</speed>
+    <speed>273</speed>
+    <speed>274</speed>
+    <speed>275</speed>
+    <speed>275</speed>
+    <speed>272</speed>
+    <speed>270</speed>
+    <speed>268</speed>
+    <speed>278</speed>
+    <speed>268</speed>
+    <speed>268</speed>
+    <speed>280</speed>
+    <speed>271</speed>
+    <speed>272</speed>
+    <speed>273</speed>
+    <speed>273</speed>
+    <speed>273</speed>
+    <speed>272</speed>
+    <speed>271</speed>
+    <speed>283</speed>
+    <speed>273</speed>
+    <speed>273</speed>
+    <speed>285</speed>
+    <speed>275</speed>
+    <speed>276</speed>
+    <speed>276</speed>
+    <speed>276</speed>
+    <speed>287</speed>
+    <speed>277</speed>
+    <speed>277</speed>
+    <speed>288</speed>
+    <speed>278</speed>
+    <speed>278</speed>
+    <speed>268</speed>
+    <speed>271</speed>
+    <speed>277</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>A318</name>
+  <adflag>A</adflag>
+  <flightid>FFT106</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:05-05</when>
+    <when>2010-05-01T13:00:09-05</when>
+    <when>2010-05-01T13:00:14-05</when>
+    <when>2010-05-01T13:00:19-05</when>
+    <when>2010-05-01T13:00:23-05</when>
+    <when>2010-05-01T13:00:28-05</when>
+    <when>2010-05-01T13:00:33-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:42-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:56-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <when>2010-05-01T13:01:05-05</when>
+    <when>2010-05-01T13:01:10-05</when>
+    <when>2010-05-01T13:01:14-05</when>
+    <when>2010-05-01T13:01:19-05</when>
+    <when>2010-05-01T13:01:24-05</when>
+    <when>2010-05-01T13:01:28-05</when>
+    <when>2010-05-01T13:01:33-05</when>
+    <when>2010-05-01T13:01:37-05</when>
+    <when>2010-05-01T13:01:42-05</when>
+    <when>2010-05-01T13:01:47-05</when>
+    <when>2010-05-01T13:01:51-05</when>
+    <when>2010-05-01T13:01:56-05</when>
+    <when>2010-05-01T13:02:01-05</when>
+    <when>2010-05-01T13:02:05-05</when>
+    <when>2010-05-01T13:02:10-05</when>
+    <when>2010-05-01T13:02:15-05</when>
+    <when>2010-05-01T13:02:19-05</when>
+    <when>2010-05-01T13:02:24-05</when>
+    <when>2010-05-01T13:02:28-05</when>
+    <when>2010-05-01T13:02:33-05</when>
+    <when>2010-05-01T13:02:38-05</when>
+    <when>2010-05-01T13:02:42-05</when>
+    <when>2010-05-01T13:02:47-05</when>
+    <when>2010-05-01T13:02:52-05</when>
+    <when>2010-05-01T13:02:56-05</when>
+    <when>2010-05-01T13:03:01-05</when>
+    <when>2010-05-01T13:03:06-05</when>
+    <when>2010-05-01T13:03:10-05</when>
+    <when>2010-05-01T13:03:15-05</when>
+    <when>2010-05-01T13:03:19-05</when>
+    <when>2010-05-01T13:03:24-05</when>
+    <when>2010-05-01T13:03:29-05</when>
+    <when>2010-05-01T13:03:33-05</when>
+    <when>2010-05-01T13:03:38-05</when>
+    <when>2010-05-01T13:03:43-05</when>
+    <when>2010-05-01T13:03:47-05</when>
+    <when>2010-05-01T13:03:52-05</when>
+    <when>2010-05-01T13:03:56-05</when>
+    <when>2010-05-01T13:04:01-05</when>
+    <when>2010-05-01T13:04:05-05</when>
+    <when>2010-05-01T13:04:10-05</when>
+    <when>2010-05-01T13:04:14-05</when>
+    <when>2010-05-01T13:04:18-05</when>
+    <when>2010-05-01T13:04:23-05</when>
+    <when>2010-05-01T13:04:27-05</when>
+    <when>2010-05-01T13:04:32-05</when>
+    <when>2010-05-01T13:04:37-05</when>
+    <when>2010-05-01T13:04:41-05</when>
+    <when>2010-05-01T13:04:46-05</when>
+    <when>2010-05-01T13:04:50-05</when>
+    <when>2010-05-01T13:04:55-05</when>
+    <when>2010-05-01T13:04:59-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.2974568508014 45.0687622602847 1432</gx:coord>
+    <gx:coord>-93.2934457905393 45.0660257042941 1371</gx:coord>
+    <gx:coord>-93.2902010482642 45.0627382200457 1341</gx:coord>
+    <gx:coord>-93.2880735868205 45.0592062737728 1280</gx:coord>
+    <gx:coord>-93.2866251180089 45.0556538417996 1280</gx:coord>
+    <gx:coord>-93.2855706436895 45.0521555770546 1249</gx:coord>
+    <gx:coord>-93.2848929213344 45.0486326683558 1249</gx:coord>
+    <gx:coord>-93.284149302237 45.0450445279501 1219</gx:coord>
+    <gx:coord>-93.2832681542582 45.0414770478452 1219</gx:coord>
+    <gx:coord>-93.2822163760078 45.0378266141909 1219</gx:coord>
+    <gx:coord>-93.2810695206555 45.0339762188888 1249</gx:coord>
+    <gx:coord>-93.2800852709943 45.0300242656845 1249</gx:coord>
+    <gx:coord>-93.2789451826991 45.026165428423 1249</gx:coord>
+    <gx:coord>-93.2776553627852 45.0222881273358 1219</gx:coord>
+    <gx:coord>-93.2762849051262 45.0183879412865 1219</gx:coord>
+    <gx:coord>-93.2750227859231 45.01452278975 1188</gx:coord>
+    <gx:coord>-93.2739788608525 45.0107480537055 1188</gx:coord>
+    <gx:coord>-93.27273416536 45.0071654180353 1158</gx:coord>
+    <gx:coord>-93.271440533456 45.0036211770402 1127</gx:coord>
+    <gx:coord>-93.2702510339155 45.0000676438878 1066</gx:coord>
+    <gx:coord>-93.2689856900965 44.9965088916327 1036</gx:coord>
+    <gx:coord>-93.2677450407515 44.9930289132183 1006</gx:coord>
+    <gx:coord>-93.2665628070763 44.9897678001495 975</gx:coord>
+    <gx:coord>-93.2654695900875 44.9865668331562 945</gx:coord>
+    <gx:coord>-93.2643275310433 44.9833330918205 914</gx:coord>
+    <gx:coord>-93.2631023843797 44.9801905024626 823</gx:coord>
+    <gx:coord>-93.2621060751847 44.9769860428905 823</gx:coord>
+    <gx:coord>-93.2613793333571 44.9737243608145 762</gx:coord>
+    <gx:coord>-93.2609358268711 44.970517162552 762</gx:coord>
+    <gx:coord>-93.260628015146 44.9674064044388 762</gx:coord>
+    <gx:coord>-93.2602996952247 44.9643597216492 731</gx:coord>
+    <gx:coord>-93.2599595576737 44.9613320303757 731</gx:coord>
+    <gx:coord>-93.2594994071955 44.9582185681901 701</gx:coord>
+    <gx:coord>-93.2589507888497 44.9549930481613 670</gx:coord>
+    <gx:coord>-93.2583578824759 44.9518211731838 670</gx:coord>
+    <gx:coord>-93.2577038531017 44.9485831657195 640</gx:coord>
+    <gx:coord>-93.2570809594468 44.9453063523228 609</gx:coord>
+    <gx:coord>-93.2563271653062 44.942138873467 609</gx:coord>
+    <gx:coord>-93.2554358149374 44.9390293085691 579</gx:coord>
+    <gx:coord>-93.2546255139468 44.9359025243045 579</gx:coord>
+    <gx:coord>-93.2538265267143 44.9327450699088 548</gx:coord>
+    <gx:coord>-93.2530252021259 44.9297128380021 548</gx:coord>
+    <gx:coord>-93.2522809727351 44.9267689034144 518</gx:coord>
+    <gx:coord>-93.2515035867768 44.9237188014152 487</gx:coord>
+    <gx:coord>-93.2506543465894 44.9207369723461 487</gx:coord>
+    <gx:coord>-93.2498548488919 44.9178124047958 457</gx:coord>
+    <gx:coord>-93.2489961276719 44.9148538675761 426</gx:coord>
+    <gx:coord>-93.2481063345252 44.9118432075909 426</gx:coord>
+    <gx:coord>-93.2475702164253 44.9090871778968 396</gx:coord>
+    <gx:coord>-93.2468054019883 44.9062896891392 365</gx:coord>
+    <gx:coord>-93.2459138821779 44.9031220636101 365</gx:coord>
+    <gx:coord>-93.2451839956313 44.9003646144392 335</gx:coord>
+    <gx:coord>-93.2442620734973 44.8974631820496 335</gx:coord>
+    <gx:coord>-93.2437934615496 44.8946084310426 335</gx:coord>
+    <gx:coord>-93.2430623256379 44.8915836945618 365</gx:coord>
+    <gx:coord>-93.2424772474959 44.8888394893853 426</gx:coord>
+    <gx:coord>-93.2417795129824 44.8858318116166 487</gx:coord>
+    <gx:coord>-93.2411065382114 44.882678391429 518</gx:coord>
+    <gx:coord>-93.2402313646157 44.879530182788 579</gx:coord>
+    <gx:coord>-93.2392009410817 44.8759747599643 609</gx:coord>
+    <gx:coord>-93.2377852820119 44.872769339825 670</gx:coord>
+    <gx:coord>-93.2363530715176 44.8696281486003 731</gx:coord>
+    <gx:coord>-93.23475664131 44.866270773938 762</gx:coord>
+    <gx:coord>-93.2331575993176 44.8629492601519 823</gx:coord>
+    <gx:coord>-93.2317272590921 44.8596791368118 853</gx:coord>
+    <gx:coord>-93.2301662617953 44.8564215369107 884</gx:coord>
+    <gx:coord>-93.2298549002314 44.8557795687872 884</gx:coord>
+    <gx:angles>140 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <speed>212</speed>
+    <speed>205</speed>
+    <speed>208</speed>
+    <speed>203</speed>
+    <speed>201</speed>
+    <speed>196</speed>
+    <speed>196</speed>
+    <speed>197</speed>
+    <speed>202</speed>
+    <speed>205</speed>
+    <speed>216</speed>
+    <speed>212</speed>
+    <speed>214</speed>
+    <speed>221</speed>
+    <speed>210</speed>
+    <speed>208</speed>
+    <speed>205</speed>
+    <speed>202</speed>
+    <speed>206</speed>
+    <speed>194</speed>
+    <speed>191</speed>
+    <speed>195</speed>
+    <speed>184</speed>
+    <speed>181</speed>
+    <speed>178</speed>
+    <speed>177</speed>
+    <speed>175</speed>
+    <speed>173</speed>
+    <speed>171</speed>
+    <speed>176</speed>
+    <speed>169</speed>
+    <speed>168</speed>
+    <speed>176</speed>
+    <speed>172</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>172</speed>
+    <speed>169</speed>
+    <speed>175</speed>
+    <speed>167</speed>
+    <speed>165</speed>
+    <speed>170</speed>
+    <speed>164</speed>
+    <speed>162</speed>
+    <speed>159</speed>
+    <speed>161</speed>
+    <speed>165</speed>
+    <speed>158</speed>
+    <speed>163</speed>
+    <speed>165</speed>
+    <speed>164</speed>
+    <speed>169</speed>
+    <speed>167</speed>
+    <speed>175</speed>
+    <speed>175</speed>
+    <speed>178</speed>
+    <speed>183</speed>
+    <speed>181</speed>
+    <speed>191</speed>
+    <speed>186</speed>
+    <speed>192</speed>
+    <speed>192</speed>
+    <speed>189</speed>
+    <speed>193</speed>
+    <speed>184</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>BE35</name>
+  <adflag>A</adflag>
+  <flightid>N46JJ</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:01:21-05</when>
+    <when>2010-05-01T13:01:26-05</when>
+    <when>2010-05-01T13:01:31-05</when>
+    <when>2010-05-01T13:01:35-05</when>
+    <when>2010-05-01T13:01:40-05</when>
+    <when>2010-05-01T13:01:44-05</when>
+    <when>2010-05-01T13:01:49-05</when>
+    <when>2010-05-01T13:01:54-05</when>
+    <when>2010-05-01T13:01:58-05</when>
+    <when>2010-05-01T13:02:03-05</when>
+    <when>2010-05-01T13:02:08-05</when>
+    <when>2010-05-01T13:02:12-05</when>
+    <when>2010-05-01T13:02:17-05</when>
+    <when>2010-05-01T13:02:22-05</when>
+    <when>2010-05-01T13:02:26-05</when>
+    <when>2010-05-01T13:02:31-05</when>
+    <when>2010-05-01T13:02:35-05</when>
+    <when>2010-05-01T13:02:40-05</when>
+    <when>2010-05-01T13:02:45-05</when>
+    <when>2010-05-01T13:02:49-05</when>
+    <when>2010-05-01T13:02:54-05</when>
+    <when>2010-05-01T13:02:59-05</when>
+    <when>2010-05-01T13:03:03-05</when>
+    <when>2010-05-01T13:03:08-05</when>
+    <when>2010-05-01T13:03:13-05</when>
+    <when>2010-05-01T13:03:17-05</when>
+    <when>2010-05-01T13:03:22-05</when>
+    <when>2010-05-01T13:03:26-05</when>
+    <when>2010-05-01T13:03:31-05</when>
+    <when>2010-05-01T13:03:36-05</when>
+    <when>2010-05-01T13:03:40-05</when>
+    <when>2010-05-01T13:03:45-05</when>
+    <when>2010-05-01T13:03:50-05</when>
+    <when>2010-05-01T13:03:54-05</when>
+    <when>2010-05-01T13:03:59-05</when>
+    <when>2010-05-01T13:04:04-05</when>
+    <when>2010-05-01T13:04:08-05</when>
+    <when>2010-05-01T13:04:13-05</when>
+    <when>2010-05-01T13:04:17-05</when>
+    <when>2010-05-01T13:04:22-05</when>
+    <when>2010-05-01T13:04:27-05</when>
+    <when>2010-05-01T13:04:31-05</when>
+    <when>2010-05-01T13:04:36-05</when>
+    <when>2010-05-01T13:04:41-05</when>
+    <when>2010-05-01T13:04:45-05</when>
+    <when>2010-05-01T13:04:50-05</when>
+    <when>2010-05-01T13:04:55-05</when>
+    <when>2010-05-01T13:04:59-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.9339221048924 44.2950315742565 1524</gx:coord>
+    <gx:coord>-92.9350064014678 44.2979570591066 1524</gx:coord>
+    <gx:coord>-92.937652997869 44.3004478107577 1524</gx:coord>
+    <gx:coord>-92.9407116824041 44.302846514598 1524</gx:coord>
+    <gx:coord>-92.9430921358657 44.3054902041603 1524</gx:coord>
+    <gx:coord>-92.9452136372834 44.308154578993 1524</gx:coord>
+    <gx:coord>-92.9479783757094 44.310667507076 1524</gx:coord>
+    <gx:coord>-92.9505645579644 44.3132980584321 1524</gx:coord>
+    <gx:coord>-92.953176931421 44.3159244553921 1524</gx:coord>
+    <gx:coord>-92.955790238918 44.3185524033008 1524</gx:coord>
+    <gx:coord>-92.9581111706922 44.3212990950149 1524</gx:coord>
+    <gx:coord>-92.9605941160522 44.3239309610271 1524</gx:coord>
+    <gx:coord>-92.9634150903891 44.3264339577567 1524</gx:coord>
+    <gx:coord>-92.9661669042714 44.3290084280208 1524</gx:coord>
+    <gx:coord>-92.9689057275993 44.3316511959644 1524</gx:coord>
+    <gx:coord>-92.9719191039836 44.3342289723207 1524</gx:coord>
+    <gx:coord>-92.9745609220571 44.3367593382531 1524</gx:coord>
+    <gx:coord>-92.9767073261514 44.3394303305052 1524</gx:coord>
+    <gx:coord>-92.9791044580601 44.34211951331 1524</gx:coord>
+    <gx:coord>-92.9818312662522 44.3446672608847 1524</gx:coord>
+    <gx:coord>-92.98437591379 44.3472600312903 1524</gx:coord>
+    <gx:coord>-92.9873161522272 44.3497184463263 1524</gx:coord>
+    <gx:coord>-92.9898453395122 44.3523721849065 1524</gx:coord>
+    <gx:coord>-92.992276996923 44.3551963485207 1524</gx:coord>
+    <gx:coord>-92.9947092219658 44.3579338326741 1524</gx:coord>
+    <gx:coord>-92.9972281517299 44.3606240814545 1524</gx:coord>
+    <gx:coord>-92.9993151368602 44.3634480822621 1524</gx:coord>
+    <gx:coord>-93.0016285033253 44.3662342282271 1524</gx:coord>
+    <gx:coord>-93.0048280633172 44.3687843972879 1524</gx:coord>
+    <gx:coord>-93.0078776508536 44.371448246948 1524</gx:coord>
+    <gx:coord>-93.0107556818704 44.3741327819505 1524</gx:coord>
+    <gx:coord>-93.0132474745541 44.3767834196569 1524</gx:coord>
+    <gx:coord>-93.015638082508 44.3795081186135 1524</gx:coord>
+    <gx:coord>-93.0183495942011 44.3821828750482 1524</gx:coord>
+    <gx:coord>-93.0215077436058 44.3847489346551 1524</gx:coord>
+    <gx:coord>-93.024007943771 44.3874959321693 1524</gx:coord>
+    <gx:coord>-93.0264526837138 44.3902468927735 1524</gx:coord>
+    <gx:coord>-93.0287728968074 44.3929994156644 1524</gx:coord>
+    <gx:coord>-93.0313252807714 44.3957423196104 1524</gx:coord>
+    <gx:coord>-93.0340309029643 44.3984682572521 1554</gx:coord>
+    <gx:coord>-93.0367834033903 44.4012140197658 1554</gx:coord>
+    <gx:coord>-93.039886374743 44.4039013532069 1524</gx:coord>
+    <gx:coord>-93.0431213002073 44.4066598090273 1524</gx:coord>
+    <gx:coord>-93.0456886621799 44.4095616223744 1524</gx:coord>
+    <gx:coord>-93.0477227123297 44.4124371862128 1524</gx:coord>
+    <gx:coord>-93.0506396295538 44.4152339455378 1524</gx:coord>
+    <gx:coord>-93.0533566431572 44.4181925397398 1524</gx:coord>
+    <gx:coord>-93.0556214357794 44.421167115874 1524</gx:coord>
+    <gx:coord>-93.0562077996189 44.4217279400145 1524</gx:coord>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>320 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <gx:angles>330 0 0</gx:angles>
+    <speed>169</speed>
+    <speed>166</speed>
+    <speed>171</speed>
+    <speed>169</speed>
+    <speed>171</speed>
+    <speed>178</speed>
+    <speed>171</speed>
+    <speed>172</speed>
+    <speed>173</speed>
+    <speed>173</speed>
+    <speed>173</speed>
+    <speed>174</speed>
+    <speed>175</speed>
+    <speed>181</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>180</speed>
+    <speed>172</speed>
+    <speed>171</speed>
+    <speed>172</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>174</speed>
+    <speed>175</speed>
+    <speed>181</speed>
+    <speed>176</speed>
+    <speed>177</speed>
+    <speed>186</speed>
+    <speed>179</speed>
+    <speed>179</speed>
+    <speed>179</speed>
+    <speed>179</speed>
+    <speed>178</speed>
+    <speed>177</speed>
+    <speed>177</speed>
+    <speed>184</speed>
+    <speed>178</speed>
+    <speed>177</speed>
+    <speed>186</speed>
+    <speed>182</speed>
+    <speed>184</speed>
+    <speed>184</speed>
+    <speed>185</speed>
+    <speed>186</speed>
+    <speed>185</speed>
+    <speed>184</speed>
+    <speed>187</speed>
+    <speed>184</speed>
+    <speed>187</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name></name>
+  <adflag>A</adflag>
+  <flightid></flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:05-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:14-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:33-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:42-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:56-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <when>2010-05-01T13:01:05-05</when>
+    <when>2010-05-01T13:01:10-05</when>
+    <when>2010-05-01T13:01:14-05</when>
+    <when>2010-05-01T13:01:19-05</when>
+    <when>2010-05-01T13:01:24-05</when>
+    <when>2010-05-01T13:01:28-05</when>
+    <when>2010-05-01T13:01:33-05</when>
+    <when>2010-05-01T13:01:38-05</when>
+    <when>2010-05-01T13:01:43-05</when>
+    <when>2010-05-01T13:01:47-05</when>
+    <when>2010-05-01T13:01:51-05</when>
+    <when>2010-05-01T13:01:56-05</when>
+    <when>2010-05-01T13:02:01-05</when>
+    <when>2010-05-01T13:02:05-05</when>
+    <when>2010-05-01T13:02:10-05</when>
+    <when>2010-05-01T13:02:15-05</when>
+    <when>2010-05-01T13:02:19-05</when>
+    <when>2010-05-01T13:02:24-05</when>
+    <when>2010-05-01T13:02:28-05</when>
+    <when>2010-05-01T13:02:33-05</when>
+    <when>2010-05-01T13:02:38-05</when>
+    <when>2010-05-01T13:02:42-05</when>
+    <when>2010-05-01T13:02:47-05</when>
+    <when>2010-05-01T13:02:52-05</when>
+    <when>2010-05-01T13:02:56-05</when>
+    <when>2010-05-01T13:03:01-05</when>
+    <when>2010-05-01T13:03:06-05</when>
+    <when>2010-05-01T13:03:10-05</when>
+    <when>2010-05-01T13:03:15-05</when>
+    <when>2010-05-01T13:03:20-05</when>
+    <when>2010-05-01T13:03:24-05</when>
+    <when>2010-05-01T13:03:29-05</when>
+    <when>2010-05-01T13:03:33-05</when>
+    <when>2010-05-01T13:03:38-05</when>
+    <when>2010-05-01T13:03:43-05</when>
+    <when>2010-05-01T13:03:47-05</when>
+    <when>2010-05-01T13:03:52-05</when>
+    <when>2010-05-01T13:03:57-05</when>
+    <when>2010-05-01T13:04:01-05</when>
+    <when>2010-05-01T13:04:06-05</when>
+    <when>2010-05-01T13:04:11-05</when>
+    <when>2010-05-01T13:04:15-05</when>
+    <when>2010-05-01T13:04:20-05</when>
+    <when>2010-05-01T13:04:24-05</when>
+    <when>2010-05-01T13:04:29-05</when>
+    <when>2010-05-01T13:04:34-05</when>
+    <when>2010-05-01T13:04:38-05</when>
+    <when>2010-05-01T13:04:43-05</when>
+    <when>2010-05-01T13:04:48-05</when>
+    <when>2010-05-01T13:04:52-05</when>
+    <when>2010-05-01T13:04:57-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.5287325331323 45.3502794027397 731</gx:coord>
+    <gx:coord>-93.5305174337715 45.3463816209029 731</gx:coord>
+    <gx:coord>-93.532323089283 45.3433065196778 731</gx:coord>
+    <gx:coord>-93.5344374505075 45.3397938806867 731</gx:coord>
+    <gx:coord>-93.5365879669744 45.3355152994798 731</gx:coord>
+    <gx:coord>-93.538455345577 45.3317693717468 731</gx:coord>
+    <gx:coord>-93.5402440337749 45.3288175816964 731</gx:coord>
+    <gx:coord>-93.5420054353005 45.3261482119682 701</gx:coord>
+    <gx:coord>-93.5437972875724 45.3236486426325 701</gx:coord>
+    <gx:coord>-93.5449025453586 45.3213557809437 670</gx:coord>
+    <gx:coord>-93.5460939368394 45.3190373998605 670</gx:coord>
+    <gx:coord>-93.5479457332637 45.3165177805485 670</gx:coord>
+    <gx:coord>-93.5493974388824 45.3141793458801 670</gx:coord>
+    <gx:coord>-93.5513867211372 45.311763387862 640</gx:coord>
+    <gx:coord>-93.5535208279901 45.3092989037314 640</gx:coord>
+    <gx:coord>-93.5553972702218 45.3069522366272 609</gx:coord>
+    <gx:coord>-93.5571429777693 45.3046054644141 609</gx:coord>
+    <gx:coord>-93.5579199353617 45.3025960765579 640</gx:coord>
+    <gx:coord>-93.5593045947048 45.3003990165413 640</gx:coord>
+    <gx:coord>-93.5616831509882 45.2976828740205 640</gx:coord>
+    <gx:coord>-93.5637771433208 45.2950299257309 640</gx:coord>
+    <gx:coord>-93.5655282859852 45.2925928168771 640</gx:coord>
+    <gx:coord>-93.5670151031996 45.2901828629185 640</gx:coord>
+    <gx:coord>-93.5687097888584 45.2875722909995 609</gx:coord>
+    <gx:coord>-93.5700169391262 45.2851834796592 670</gx:coord>
+    <gx:coord>-93.5710302700083 45.2828077246619 640</gx:coord>
+    <gx:coord>-93.5718507391893 45.2803449539575 670</gx:coord>
+    <gx:coord>-93.5725921190677 45.2778546051997 670</gx:coord>
+    <gx:coord>-93.5735869984384 45.2752499819516 670</gx:coord>
+    <gx:coord>-93.5746474214783 45.2726078789038 670</gx:coord>
+    <gx:coord>-93.5759690717845 45.2698099999195 670</gx:coord>
+    <gx:coord>-93.5773880658931 45.2669964536541 701</gx:coord>
+    <gx:coord>-93.5786320195651 45.2643944197042 701</gx:coord>
+    <gx:coord>-93.5801045228797 45.2617721181735 731</gx:coord>
+    <gx:coord>-93.5812823080336 45.2592837181772 762</gx:coord>
+    <gx:coord>-93.5824999029929 45.2568982323771 792</gx:coord>
+    <gx:coord>-93.584184493492 45.2545288880291 792</gx:coord>
+    <gx:coord>-93.5856799945281 45.2523235684068 792</gx:coord>
+    <gx:coord>-93.5867865417154 45.2502484182149 792</gx:coord>
+    <gx:coord>-93.5877350378085 45.2481996073608 792</gx:coord>
+    <gx:coord>-93.5890621470214 45.2458286959404 762</gx:coord>
+    <gx:coord>-93.5904952245442 45.2433496248092 762</gx:coord>
+    <gx:coord>-93.5917459859832 45.2410175205115 762</gx:coord>
+    <gx:coord>-93.592940308901 45.2387518649986 792</gx:coord>
+    <gx:coord>-93.5943516581034 45.2363760400415 792</gx:coord>
+    <gx:coord>-93.595835737429 45.2339795097202 792</gx:coord>
+    <gx:coord>-93.5970428000944 45.2316738651172 792</gx:coord>
+    <gx:coord>-93.598068247895 45.2293303072495 792</gx:coord>
+    <gx:coord>-93.5992987604295 45.2268750160339 762</gx:coord>
+    <gx:coord>-93.6008769052334 45.2242985661919 762</gx:coord>
+    <gx:coord>-93.6025298777898 45.2216628823159 762</gx:coord>
+    <gx:coord>-93.6039679259902 45.2191586079975 762</gx:coord>
+    <gx:coord>-93.6055530853699 45.2165615203343 762</gx:coord>
+    <gx:coord>-93.6071850685486 45.213948758836 792</gx:coord>
+    <gx:coord>-93.6085800541819 45.2114666338841 792</gx:coord>
+    <gx:coord>-93.6099900017953 45.2087907684969 762</gx:coord>
+    <gx:coord>-93.6111813373289 45.2058856405005 762</gx:coord>
+    <gx:coord>-93.6116978316508 45.2030015871681 762</gx:coord>
+    <gx:coord>-93.6118935129054 45.2001474423799 762</gx:coord>
+    <gx:coord>-93.6120686576365 45.1971548169968 731</gx:coord>
+    <gx:coord>-93.6120488607103 45.1942250308012 731</gx:coord>
+    <gx:coord>-93.6121619193052 45.1911822627783 731</gx:coord>
+    <gx:coord>-93.6123153707665 45.188122812492 731</gx:coord>
+    <gx:coord>-93.6121210225109 45.1864342009565 731</gx:coord>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>210 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>190 0 0</gx:angles>
+    <gx:angles>190 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>190 0 0</gx:angles>
+    <gx:angles>190 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <speed>202</speed>
+    <speed>180</speed>
+    <speed>166</speed>
+    <speed>171</speed>
+    <speed>162</speed>
+    <speed>157</speed>
+    <speed>143</speed>
+    <speed>145</speed>
+    <speed>156</speed>
+    <speed>144</speed>
+    <speed>142</speed>
+    <speed>149</speed>
+    <speed>146</speed>
+    <speed>148</speed>
+    <speed>140</speed>
+    <speed>139</speed>
+    <speed>142</speed>
+    <speed>137</speed>
+    <speed>143</speed>
+    <speed>149</speed>
+    <speed>151</speed>
+    <speed>152</speed>
+    <speed>151</speed>
+    <speed>147</speed>
+    <speed>140</speed>
+    <speed>141</speed>
+    <speed>140</speed>
+    <speed>149</speed>
+    <speed>148</speed>
+    <speed>150</speed>
+    <speed>158</speed>
+    <speed>152</speed>
+    <speed>150</speed>
+    <speed>147</speed>
+    <speed>142</speed>
+    <speed>138</speed>
+    <speed>131</speed>
+    <speed>131</speed>
+    <speed>132</speed>
+    <speed>130</speed>
+    <speed>130</speed>
+    <speed>138</speed>
+    <speed>138</speed>
+    <speed>137</speed>
+    <speed>140</speed>
+    <speed>136</speed>
+    <speed>139</speed>
+    <speed>142</speed>
+    <speed>143</speed>
+    <speed>146</speed>
+    <speed>150</speed>
+    <speed>151</speed>
+    <speed>157</speed>
+    <speed>152</speed>
+    <speed>154</speed>
+    <speed>160</speed>
+    <speed>155</speed>
+    <speed>157</speed>
+    <speed>159</speed>
+    <speed>160</speed>
+    <speed>159</speed>
+    <speed>155</speed>
+    <speed>157</speed>
+    <speed>161</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>B752</name>
+  <adflag>A</adflag>
+  <flightid>DAL2731</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:04:40-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.3671504733075 45.0392472395977 2743</gx:coord>
+    <gx:coord>-92.3742258682339 45.0377289236059 2712</gx:coord>
+    <gx:coord>-92.3813215867021 45.0364293844267 2682</gx:coord>
+    <gx:coord>-92.3883643499875 45.0352118386382 2651</gx:coord>
+    <gx:coord>-92.3954606917206 45.0343296776778 2621</gx:coord>
+    <gx:coord>-92.3983011205325 45.0338926726637 2608.6</gx:coord>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <speed>301</speed>
+    <speed>289</speed>
+    <speed>283</speed>
+    <speed>283</speed>
+    <speed>272</speed>
+    <speed>276</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>CRJ2</name>
+  <adflag>A</adflag>
+  <flightid>SKW4805</flightid>
+  <styleUrl>#arrival</styleUrl>
+</Placemark>
+<Placemark>
+  <name>CRJ2</name>
+  <adflag>A</adflag>
+  <flightid>FLG4092</flightid>
+  <styleUrl>#arrival</styleUrl>
+</Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>CPZ5667</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:01-05</when>
+    <when>2010-05-01T13:01:06-05</when>
+    <when>2010-05-01T13:01:11-05</when>
+    <when>2010-05-01T13:01:15-05</when>
+    <when>2010-05-01T13:01:20-05</when>
+    <when>2010-05-01T13:01:24-05</when>
+    <when>2010-05-01T13:01:29-05</when>
+    <when>2010-05-01T13:01:34-05</when>
+    <when>2010-05-01T13:01:38-05</when>
+    <when>2010-05-01T13:01:43-05</when>
+    <when>2010-05-01T13:01:48-05</when>
+    <when>2010-05-01T13:01:52-05</when>
+    <when>2010-05-01T13:01:57-05</when>
+    <when>2010-05-01T13:02:02-05</when>
+    <when>2010-05-01T13:02:06-05</when>
+    <when>2010-05-01T13:02:11-05</when>
+    <when>2010-05-01T13:02:15-05</when>
+    <when>2010-05-01T13:02:20-05</when>
+    <when>2010-05-01T13:02:25-05</when>
+    <when>2010-05-01T13:02:29-05</when>
+    <when>2010-05-01T13:02:34-05</when>
+    <when>2010-05-01T13:02:39-05</when>
+    <when>2010-05-01T13:02:43-05</when>
+    <when>2010-05-01T13:02:48-05</when>
+    <when>2010-05-01T13:02:53-05</when>
+    <when>2010-05-01T13:02:57-05</when>
+    <when>2010-05-01T13:03:02-05</when>
+    <when>2010-05-01T13:03:06-05</when>
+    <when>2010-05-01T13:03:11-05</when>
+    <when>2010-05-01T13:03:16-05</when>
+    <when>2010-05-01T13:03:20-05</when>
+    <when>2010-05-01T13:03:25-05</when>
+    <when>2010-05-01T13:03:30-05</when>
+    <when>2010-05-01T13:03:34-05</when>
+    <when>2010-05-01T13:03:39-05</when>
+    <when>2010-05-01T13:03:44-05</when>
+    <when>2010-05-01T13:03:48-05</when>
+    <when>2010-05-01T13:03:53-05</when>
+    <when>2010-05-01T13:03:57-05</when>
+    <when>2010-05-01T13:04:02-05</when>
+    <when>2010-05-01T13:04:07-05</when>
+    <when>2010-05-01T13:04:11-05</when>
+    <when>2010-05-01T13:04:16-05</when>
+    <when>2010-05-01T13:04:21-05</when>
+    <when>2010-05-01T13:04:25-05</when>
+    <when>2010-05-01T13:04:30-05</when>
+    <when>2010-05-01T13:04:35-05</when>
+    <when>2010-05-01T13:04:39-05</when>
+    <when>2010-05-01T13:04:44-05</when>
+    <when>2010-05-01T13:04:49-05</when>
+    <when>2010-05-01T13:04:53-05</when>
+    <when>2010-05-01T13:04:58-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-92.9496238812799 45.0117549407746 1438.2</gx:coord>
+    <gx:coord>-92.9507065768732 45.0116702587604 1432</gx:coord>
+    <gx:coord>-92.9563739191926 45.0116271226204 1432</gx:coord>
+    <gx:coord>-92.9620225732021 45.0115639668496 1432</gx:coord>
+    <gx:coord>-92.9673675587699 45.0113432900049 1402</gx:coord>
+    <gx:coord>-92.9725115032188 45.0111442254373 1402</gx:coord>
+    <gx:coord>-92.9778810091229 45.0112050922639 1371</gx:coord>
+    <gx:coord>-92.9832227114571 45.0112143826731 1371</gx:coord>
+    <gx:coord>-92.9884546803523 45.0110418166788 1341</gx:coord>
+    <gx:coord>-92.9938268606229 45.0109652220709 1341</gx:coord>
+    <gx:coord>-92.9991151069756 45.010802144845 1310</gx:coord>
+    <gx:coord>-93.0041467584036 45.0105516668541 1310</gx:coord>
+    <gx:coord>-93.0090742909164 45.0105233046799 1280</gx:coord>
+    <gx:coord>-93.0139435770527 45.0106265340001 1280</gx:coord>
+    <gx:coord>-93.0186698179379 45.010634924101 1249</gx:coord>
+    <gx:coord>-93.0233769482656 45.0105798571028 1219</gx:coord>
+    <gx:coord>-93.027863445495 45.0103319372353 1219</gx:coord>
+    <gx:coord>-93.0321355024912 45.009785470284 1188</gx:coord>
+    <gx:coord>-93.0364774006258 45.0090804055343 1188</gx:coord>
+    <gx:coord>-93.0406972054631 45.008159893417 1158</gx:coord>
+    <gx:coord>-93.044688438093 45.0070424610069 1158</gx:coord>
+    <gx:coord>-93.048236193366 45.0055626328365 1127</gx:coord>
+    <gx:coord>-93.0515060655523 45.0038918034748 1097</gx:coord>
+    <gx:coord>-93.0547412568513 45.002203639943 1097</gx:coord>
+    <gx:coord>-93.057960971331 45.0002785469345 1066</gx:coord>
+    <gx:coord>-93.061163597597 44.9982000732934 1036</gx:coord>
+    <gx:coord>-93.0642340616386 44.9961004469539 1036</gx:coord>
+    <gx:coord>-93.0673288162316 44.9939827866134 1036</gx:coord>
+    <gx:coord>-93.0705257535347 44.9919340234479 1006</gx:coord>
+    <gx:coord>-93.0737651809484 44.9898497469776 1006</gx:coord>
+    <gx:coord>-93.0766698334355 44.9874752633062 975</gx:coord>
+    <gx:coord>-93.0795448300029 44.9851003293423 945</gx:coord>
+    <gx:coord>-93.0826513591394 44.982853369523 914</gx:coord>
+    <gx:coord>-93.0857494236443 44.9806128435883 914</gx:coord>
+    <gx:coord>-93.0889594989987 44.9783354445401 884</gx:coord>
+    <gx:coord>-93.0921516080765 44.9761326356492 853</gx:coord>
+    <gx:coord>-93.0951593343498 44.9739412329465 823</gx:coord>
+    <gx:coord>-93.098173526634 44.9718087345519 792</gx:coord>
+    <gx:coord>-93.1011828507638 44.9697896030084 792</gx:coord>
+    <gx:coord>-93.1041138105741 44.9676784537011 762</gx:coord>
+    <gx:coord>-93.1070716804749 44.9654796588945 762</gx:coord>
+    <gx:coord>-93.1101959375488 44.9632479940121 731</gx:coord>
+    <gx:coord>-93.1134259541861 44.9611142324701 731</gx:coord>
+    <gx:coord>-93.1164777263599 44.9590021654861 701</gx:coord>
+    <gx:coord>-93.119453084479 44.9567137200248 701</gx:coord>
+    <gx:coord>-93.1225749783361 44.9543749518252 670</gx:coord>
+    <gx:coord>-93.1257330391052 44.9521434289046 640</gx:coord>
+    <gx:coord>-93.1288583838247 44.9499086265813 640</gx:coord>
+    <gx:coord>-93.1320823896043 44.947732382611 609</gx:coord>
+    <gx:coord>-93.1352777130563 44.9456935460161 609</gx:coord>
+    <gx:coord>-93.1382372228923 44.9435026223594 579</gx:coord>
+    <gx:coord>-93.1412308158626 44.9413228585563 548</gx:coord>
+    <gx:coord>-93.1440834422772 44.9393578781327 548</gx:coord>
+    <gx:coord>-93.1468380987104 44.937418270883 548</gx:coord>
+    <gx:coord>-93.1496706928566 44.9354098449433 548</gx:coord>
+    <gx:coord>-93.1524193130388 44.9334175710809 548</gx:coord>
+    <gx:coord>-93.1552204975698 44.931467153437 548</gx:coord>
+    <gx:coord>-93.1580221467789 44.9294054329873 548</gx:coord>
+    <gx:coord>-93.1608324983225 44.9273103160518 548</gx:coord>
+    <gx:coord>-93.163576735833 44.9252792086421 518</gx:coord>
+    <gx:coord>-93.1662777029414 44.923281165701 518</gx:coord>
+    <gx:coord>-93.1691629183162 44.9213004519466 518</gx:coord>
+    <gx:coord>-93.1721326207182 44.9193080290794 487</gx:coord>
+    <gx:coord>-93.1750564756636 44.9172689130085 487</gx:coord>
+    <gx:coord>-93.1778338144972 44.915261757476 457</gx:coord>
+    <gx:coord>-93.1805696776089 44.9132626732327 457</gx:coord>
+    <gx:coord>-93.1819903937475 44.9122233325116 441.5</gx:coord>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>240 0 0</gx:angles>
+    <gx:angles>240 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <speed>214</speed>
+    <speed>207</speed>
+    <speed>202</speed>
+    <speed>208</speed>
+    <speed>207</speed>
+    <speed>205</speed>
+    <speed>203</speed>
+    <speed>202</speed>
+    <speed>209</speed>
+    <speed>199</speed>
+    <speed>196</speed>
+    <speed>200</speed>
+    <speed>188</speed>
+    <speed>183</speed>
+    <speed>178</speed>
+    <speed>175</speed>
+    <speed>179</speed>
+    <speed>170</speed>
+    <speed>166</speed>
+    <speed>169</speed>
+    <speed>161</speed>
+    <speed>160</speed>
+    <speed>159</speed>
+    <speed>159</speed>
+    <speed>160</speed>
+    <speed>162</speed>
+    <speed>164</speed>
+    <speed>172</speed>
+    <speed>166</speed>
+    <speed>167</speed>
+    <speed>174</speed>
+    <speed>169</speed>
+    <speed>170</speed>
+    <speed>169</speed>
+    <speed>168</speed>
+    <speed>166</speed>
+    <speed>165</speed>
+    <speed>163</speed>
+    <speed>169</speed>
+    <speed>164</speed>
+    <speed>164</speed>
+    <speed>172</speed>
+    <speed>168</speed>
+    <speed>169</speed>
+    <speed>169</speed>
+    <speed>169</speed>
+    <speed>169</speed>
+    <speed>168</speed>
+    <speed>167</speed>
+    <speed>170</speed>
+    <speed>160</speed>
+    <speed>158</speed>
+    <speed>161</speed>
+    <speed>153</speed>
+    <speed>151</speed>
+    <speed>152</speed>
+    <speed>153</speed>
+    <speed>152</speed>
+    <speed>153</speed>
+    <speed>154</speed>
+    <speed>154</speed>
+    <speed>153</speed>
+    <speed>153</speed>
+    <speed>160</speed>
+    <speed>156</speed>
+    <speed>160</speed>
+    <speed>164</speed>
+</gx:Track></Placemark>
+</Folder>
+<Folder>
+  <name>Departures</name>
+<Placemark>
+  <name>TEX2</name>
+  <adflag>D</adflag>
+  <flightid>HOOK67</flightid>
+  <styleUrl>#departure</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:02:46-05</when>
+    <when>2010-05-01T13:02:50-05</when>
+    <when>2010-05-01T13:02:54-05</when>
+    <when>2010-05-01T13:02:59-05</when>
+    <when>2010-05-01T13:03:04-05</when>
+    <when>2010-05-01T13:03:08-05</when>
+    <when>2010-05-01T13:03:13-05</when>
+    <when>2010-05-01T13:03:18-05</when>
+    <when>2010-05-01T13:03:22-05</when>
+    <when>2010-05-01T13:03:27-05</when>
+    <when>2010-05-01T13:03:31-05</when>
+    <when>2010-05-01T13:03:36-05</when>
+    <when>2010-05-01T13:03:41-05</when>
+    <when>2010-05-01T13:03:45-05</when>
+    <when>2010-05-01T13:03:50-05</when>
+    <when>2010-05-01T13:03:55-05</when>
+    <when>2010-05-01T13:03:59-05</when>
+    <when>2010-05-01T13:04:04-05</when>
+    <when>2010-05-01T13:04:09-05</when>
+    <when>2010-05-01T13:04:13-05</when>
+    <when>2010-05-01T13:04:18-05</when>
+    <when>2010-05-01T13:04:23-05</when>
+    <when>2010-05-01T13:04:28-05</when>
+    <when>2010-05-01T13:04:32-05</when>
+    <when>2010-05-01T13:04:37-05</when>
+    <when>2010-05-01T13:04:42-05</when>
+    <when>2010-05-01T13:04:46-05</when>
+    <when>2010-05-01T13:04:51-05</when>
+    <when>2010-05-01T13:04:56-05</when>
+    <when>2010-05-01T13:05:00-05</when>
+    <gx:coord>-93.2379571205595 44.872806349747 365</gx:coord>
+    <gx:coord>-93.2370660925484 44.870006118743 396</gx:coord>
+    <gx:coord>-93.236355767523 44.8669752777211 426</gx:coord>
+    <gx:coord>-93.2354887209031 44.863712193489 487</gx:coord>
+    <gx:coord>-93.2347087148419 44.8604536579846 548</gx:coord>
+    <gx:coord>-93.2338531241111 44.8572464977323 609</gx:coord>
+    <gx:coord>-93.2329069833652 44.8540674818656 670</gx:coord>
+    <gx:coord>-93.2321075679892 44.8508271074111 731</gx:coord>
+    <gx:coord>-93.2318979317232 44.8475791496379 792</gx:coord>
+    <gx:coord>-93.2324245825346 44.8444239832126 884</gx:coord>
+    <gx:coord>-93.2337414411031 44.8414077607553 945</gx:coord>
+    <gx:coord>-93.2358704572033 44.8386783246771 1006</gx:coord>
+    <gx:coord>-93.2388663703645 44.836365445841 1066</gx:coord>
+    <gx:coord>-93.2426861295915 44.8345537010783 1127</gx:coord>
+    <gx:coord>-93.2472528925157 44.8333824186694 1158</gx:coord>
+    <gx:coord>-93.252467378877 44.8329692039001 1188</gx:coord>
+    <gx:coord>-93.25805239674 44.8333893976675 1219</gx:coord>
+    <gx:coord>-93.2638450577518 44.8346083411457 1219</gx:coord>
+    <gx:coord>-93.2696754993405 44.83650914188 1219</gx:coord>
+    <gx:coord>-93.2753673121587 44.8390951418887 1219</gx:coord>
+    <gx:coord>-93.2808543977574 44.8421681587795 1219</gx:coord>
+    <gx:coord>-93.2861853262416 44.8454128516506 1249</gx:coord>
+    <gx:coord>-93.29145969331 44.8487370983379 1219</gx:coord>
+    <gx:coord>-93.2967095159 44.8520389729185 1219</gx:coord>
+    <gx:coord>-93.3019214165294 44.8553364257712 1219</gx:coord>
+    <gx:coord>-93.3070477220233 44.8587223340278 1219</gx:coord>
+    <gx:coord>-93.3121286565238 44.8620050415952 1219</gx:coord>
+    <gx:coord>-93.3171626530446 44.8652559523285 1219</gx:coord>
+    <gx:coord>-93.3221179929219 44.868582313462 1219</gx:coord>
+    <gx:coord>-93.3270963865766 44.8718050975636 1219</gx:coord>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>180 0 0</gx:angles>
+    <gx:angles>190 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>240 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <gx:angles>310 0 0</gx:angles>
+    <speed>178</speed>
+    <speed>175</speed>
+    <speed>180</speed>
+    <speed>177</speed>
+    <speed>175</speed>
+    <speed>177</speed>
+    <speed>175</speed>
+    <speed>181</speed>
+    <speed>173</speed>
+    <speed>172</speed>
+    <speed>178</speed>
+    <speed>173</speed>
+    <speed>178</speed>
+    <speed>187</speed>
+    <speed>196</speed>
+    <speed>208</speed>
+    <speed>224</speed>
+    <speed>237</speed>
+    <speed>247</speed>
+    <speed>247</speed>
+    <speed>263</speed>
+    <speed>266</speed>
+    <speed>258</speed>
+    <speed>267</speed>
+    <speed>266</speed>
+    <speed>265</speed>
+    <speed>263</speed>
+    <speed>266</speed>
+    <speed>270</speed>
+    <speed>260</speed>
+</gx:Track></Placemark>
+</Folder>
+<Folder>
+  <name>Overflights</name>
+</Folder>
+</Document>
+</kml>

Modified: sandbox/ahocevar/playground/examples/late-render.html
===================================================================
--- sandbox/ahocevar/playground/examples/late-render.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/late-render.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             map = new OpenLayers.Map();
             layer = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             );
             map.addLayer(layer);
@@ -24,7 +24,9 @@
   <body onload="init()">
     <h1 id="title">Late Rendering</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        creation, render, div
+    </div>
 
     <p id="shortdesc">
         Demonstrates how a map can be rendered to an empty container after

Modified: sandbox/ahocevar/playground/examples/layer-opacity.html
===================================================================
--- sandbox/ahocevar/playground/examples/layer-opacity.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/layer-opacity.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -65,7 +65,9 @@
   <body onload="init()">
     <h1 id="title">Layer Opacity Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        opacity, transparent, transparency
+    </div>
 
     <p id="shortdesc">
         Demonstrate a change in the opacity for an overlay layer.

Modified: sandbox/ahocevar/playground/examples/layerLoadMonitoring.html
===================================================================
--- sandbox/ahocevar/playground/examples/layerLoadMonitoring.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/layerLoadMonitoring.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,28 +32,28 @@
             map.addControl(new OpenLayers.Control.LayerSwitcher());
 
             buffer0 = new OpenLayers.Layer.WMS( "WMS Buffer 0",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} ,
                     { singleTile: false, buffer:0}
             );
             registerEvents(buffer0);
 
             buffer1 = new OpenLayers.Layer.WMS( "WMS Buffer 1",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} ,
                     { singleTile: false, buffer:1}
             );
             registerEvents(buffer1);
 
             buffer2 = new OpenLayers.Layer.WMS( "WMS Buffer 2",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} ,
                     { singleTile: false, buffer:2 }
             );
             registerEvents(buffer2);
 
             singleTileLayer = new OpenLayers.Layer.WMS( "Single Tile Layer",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} ,
                     { singleTile: true}
             );
@@ -107,7 +107,9 @@
   <body onload="init()">
       <h1 id="title">Layer Load Monitoring Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+        monitor, loading
+      </div>
 
       <p id="shortdesc">
           Demonstrate a method for monitoring tile loading performance.

Modified: sandbox/ahocevar/playground/examples/layerswitcher.html
===================================================================
--- sandbox/ahocevar/playground/examples/layerswitcher.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/layerswitcher.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
             map.addControl(new OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher')}));
 
             var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}, {'displayInLayerSwitcher':false} );
 
             var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
@@ -38,13 +38,14 @@
     <h1 id="title">Layer Switcher Example</h1>
 
     <div id="tags">
+        tree, layerswitcher, reposition
     </div>
 
     <p id="shortdesc">
         Demonstrates the use of the LayerSwitcher outside of the OpenLayers window.
     </p>
 
-    <div id="layerswitcher"></div>
+    <div id="layerswitcher" class="olControlLayerSwitcher"></div>
     <div id="map" class="smallmap"></div>
     <div id="docs">
       <p>This demonstrates use of the LayerSwitcher outside the map div. It also shows use

Modified: sandbox/ahocevar/playground/examples/lite.html
===================================================================
--- sandbox/ahocevar/playground/examples/lite.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/lite.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,7 @@
         function init(){
             map = new OpenLayers.Map( 'map' );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
             map.addLayer(layer);
             map.zoomToMaxExtent();
@@ -19,7 +19,9 @@
   <body onload="init()">
     <h1 id="title">Basic Single WMS Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        basic, simple, minimal, cleanup
+    </div>
 
     <div id="shortdesc">Show a Simple Map</div>
 

Modified: sandbox/ahocevar/playground/examples/mapguide.html
===================================================================
--- sandbox/ahocevar/playground/examples/mapguide.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mapguide.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -84,6 +84,7 @@
             
           var options = {
               isBaseLayer: true,
+              transitionEffect: "resize",
               buffer: 1,
               useOverlay: false,
               useAsyncOverlay: false,
@@ -125,7 +126,7 @@
             layer = new OpenLayers.Layer.MapGuide( "MapGuide OS Overlay layer", url, params, options );
             map.addLayer(layer);
             */
-            map.addControl(new OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher')}));
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
             map.zoomToMaxExtent();
     }
     </script>
@@ -134,6 +135,7 @@
     <h1 id="title">MapGuide Layer Example</h1>
 
     <div id="tags">
+        MapGuide, basic
     </div>
 
     <p id="shortdesc">
@@ -144,7 +146,6 @@
     
     <div id="map" class="smallmap"></div>
     <div id="map2">
-      <div id="layerswitcher"></div>
     </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/mapserver.html
===================================================================
--- sandbox/ahocevar/playground/examples/mapserver.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mapserver.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
         function init(){
             map = new OpenLayers.Map( 'map' );
             layer = new OpenLayers.Layer.MapServer( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'},
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'},
                     {gutter: 15});
             map.addLayer(layer);
 
@@ -24,8 +24,8 @@
     </script>
   </head>
   <body onload="init()">
-    <div id="title">MapServer Layer</div>
-    <div id="tags"></div>
+    <h1 id="title">MapServer Layer</h1>
+    <div id="tags">UMN Mapserver, tile, tiled</div>
     <div id="shortdesc">Shows MapServer Layer</div>
     <div id="map" class="smallmap"></div>
     <div id="docs">

Modified: sandbox/ahocevar/playground/examples/mapserver_untiled.html
===================================================================
--- sandbox/ahocevar/playground/examples/mapserver_untiled.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mapserver_untiled.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
         window.onload = function(){
             map = new OpenLayers.Map( 'map', {maxResolution: 'auto'} );
             var layer = new OpenLayers.Layer.MapServer( "MapServer Untiled", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'}, {singleTile: true} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'}, {singleTile: true} );
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(0, 0), 1);
             map.addControl( new OpenLayers.Control.LayerSwitcher() );
@@ -24,8 +24,10 @@
     </script>
   </head>
   <body>
-    <div id="title">MapServer Single Tile Mode</div>
-    <div id="tags"></div>
+    <h1 id="title">MapServer Single Tile Mode</h1>
+    <div id="tags">
+        UMN Mapserver, basic, singleTile
+    </div>
     <div id="shortdesc">Shows single tile MapServer Layer</div>
     <div id="map" class="smallmap"></div>
     <div id="docs">

Modified: sandbox/ahocevar/playground/examples/marker-shadow.html
===================================================================
--- sandbox/ahocevar/playground/examples/marker-shadow.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/marker-shadow.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -107,6 +107,7 @@
         <h1 id="title">Marker Shadows using Background Graphics/Z-Indexes</h1>
 
         <div id="tags">
+            markers, shadow, style
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/markerResize.html
===================================================================
--- sandbox/ahocevar/playground/examples/markerResize.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/markerResize.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,17 +11,17 @@
         function init(){
             map = new OpenLayers.Map('map');
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
                 
             map.addLayer(layer);
             var markers = new OpenLayers.Layer.Markers( "Markers" );
             map.addLayer(markers);
 
-            size = new OpenLayers.Size(50,50);
+            size = new OpenLayers.Size(21, 25);
             calculateOffset = function(size) {
                         return new OpenLayers.Pixel(-(size.w/2), -size.h); };
             icon = new OpenLayers.Icon(
-                'http://boston.openguides.org/markers/AQUA.png',
+                'http://www.openlayers.org/dev/img/marker.png',
                 size, null, calculateOffset);
             markers.addMarker(
                 new OpenLayers.Marker(new OpenLayers.LonLat(-71,40), icon));
@@ -39,8 +39,10 @@
     </script>
   </head>
   <body onload="init()">
-    <div id="title">Resize a Marker</div>
-    <div id="tags"></div>
+    <h1 id="title">Resize a Marker</h1>
+    <div id="tags">
+        animation, resizing, style, size
+    </div>
     <div id="shortdesc">Dynamically resize a marker</div>
     <div id="map" class="smallmap"></div>
     <div id="docs">


Property changes on: sandbox/ahocevar/playground/examples/marker_shadow.png
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/examples/markers.html
===================================================================
--- sandbox/ahocevar/playground/examples/markers.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/markers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             OpenLayers.ProxyHost="/proxy/?url=";
             map = new OpenLayers.Map('map');
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
                 
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
@@ -22,9 +22,9 @@
             var markers = new OpenLayers.Layer.Markers( "Markers" );
             map.addLayer(markers);
 
-            var size = new OpenLayers.Size(10,17);
+            var size = new OpenLayers.Size(21,25);
             var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
-            var icon = new OpenLayers.Icon('http://boston.openguides.org/markers/AQUA.png',size,offset);
+            var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png',size,offset);
             markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
 
             var halfIcon = icon.clone();
@@ -42,8 +42,8 @@
     </script>
   </head>
   <body onload="init()">
-    <div id="title">Markers Layer Example</div>
-    <div id="tags"></div>
+    <h1 id="title">Markers Layer Example</h1>
+    <div id="tags">Marker, event, mousedown, popup, inco</div>
     <div id="shortdesc">Show markers layer with different markers</div>
     <div id="map" class="smallmap"></div>
     <div id="docs">

Modified: sandbox/ahocevar/playground/examples/markersTextLayer.html
===================================================================
--- sandbox/ahocevar/playground/examples/markersTextLayer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/markersTextLayer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             OpenLayers.ProxyHost="/proxy/?url=";
             map = new OpenLayers.Map('map');
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
                 
             map.addLayer(layer);
 
@@ -25,6 +25,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Using a Layer.Text to display markers</h1>
+    <div id="tags">
+        textlayer, csv, tsv, basic, popup
+    </div>
     <p id="shortdesc">
       The Layer.Text class reads a Tab seperated values file and displays it as markers on
       the map.

Modified: sandbox/ahocevar/playground/examples/measure.html
===================================================================
--- sandbox/ahocevar/playground/examples/measure.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/measure.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,16 +16,20 @@
         #output {
             float: right;
         }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
     </style>
     <script src="../lib/OpenLayers.js"></script>
     <script type="text/javascript">
         var map, measureControls;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
         function init(){
             map = new OpenLayers.Map('map');
             
             var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}); 
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'}); 
 
             map.addLayers([wmsLayer]);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
@@ -128,10 +132,20 @@
                 control.geodesic = element.checked;
             }
         }
+        
+        function toggleImmediate(element) {
+            for(key in measureControls) {
+                var control = measureControls[key];
+                control.setImmediate(element.checked);
+            }
+        }
     </script>
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Measure Example</h1>
+    <div id="tags">
+        measuring, geodesic, area, length, distance
+    </div>
     <p id="shortdesc">
         Demonstrates the measure control to measure distances and areas.
     </p>
@@ -157,13 +171,19 @@
                 <input type="checkbox" name="geodesic" id="geodesicToggle" onclick="toggleGeodesic(this);" />
                 <label for="geodesicToggle">use geodesic measures</label>
             </li>
+            <li>
+                <input type="checkbox" name="immediate" id="immediateToggle" onclick="toggleImmediate(this);" />
+                <label for="immediateToggle">use immediate measures</label>
+            </li>
         </ul>
         <p>Note that the geometries drawn are planar geometries and the
         metrics returned by the measure control are planar measures by
         default.  If your map is in a geographic projection or you have the
         appropriate projection definitions to transform your geometries into
         geographic coordinates, you can set the "geodesic" property of the control
-        to true to calculate geodesic measures instead of planar measures.</p>
+        to true to calculate geodesic measures instead of planar measures.
+        Also you have the possibility to set the "immediate" property to true
+        to get a new calculated value once the mouse has been mooved.</p>
     </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/mm.html
===================================================================
--- sandbox/ahocevar/playground/examples/mm.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mm.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,7 +12,8 @@
     </style>
 
 
-    <script type="text/javascript" src="http://clients.multimap.com/API/maps/1.1/metacarta_04"></script>
+    <!-- multimap api key for http://(www.)openlayers.org -->
+    <script type="text/javascript" src="http://developer.multimap.com/API/maps/1.2/OA10072915821139765"></script>
 
 
     <script src="../lib/OpenLayers.js"></script>
@@ -50,6 +51,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">MultiMap Example</h1>
+    <div id="tags">
+        MultiMap, basic, cleanup
+    </div>
     <p id="shortdesc">
       An example of using the Layer.MultiMap class.
     </p>  

Modified: sandbox/ahocevar/playground/examples/modify-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/modify-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/modify-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,7 +21,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}); 
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'}); 
             OpenLayers.Feature.Vector.style['default']['strokeWidth'] = '2';
             vectors = new OpenLayers.Layer.Vector("Vector Layer");
 
@@ -106,6 +106,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Modify Feature Example</h1>
+    <div id="tags">
+        vertices, digitizing, draw, drawing
+    </div>
     <div id="shortdesc">A demonstration of the ModifyFeature control for editing vector features.</div>
     <div id="map" class="smallmap"></div>
     <div id="controls">

Modified: sandbox/ahocevar/playground/examples/mouse-position.html
===================================================================
--- sandbox/ahocevar/playground/examples/mouse-position.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mouse-position.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -14,7 +14,7 @@
             map.addControl(new OpenLayers.Control.MousePosition());
 
             var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'} );
 
             map.addLayers([ol_wms]);
@@ -28,7 +28,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">MousePosition Control</h3>
+    <h1 id="title">MousePosition Control</h1>
+    <div id="tags">
+        coordinate
+    </div>
     <p id="shortdesc">
       Use the MousePosition Control to display the coordinates of the cursor
       inside or outside the map div.

Copied: sandbox/ahocevar/playground/examples/mousewheel-interval.html (from rev 10919, trunk/openlayers/examples/mousewheel-interval.html)
===================================================================
--- sandbox/ahocevar/playground/examples/mousewheel-interval.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/mousewheel-interval.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,59 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Mousewheel Interval Example</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, layer;
+
+        function setCumulative() {
+            var nav = map.getControlsByClass("OpenLayers.Control.Navigation")[0];
+            var cumulative = document.getElementById("cumulative");
+            nav.handlers.wheel.cumulative = cumulative.checked;
+        }
+
+        function init(){
+            map = new OpenLayers.Map( 'map', {controls: [
+                new OpenLayers.Control.Navigation(
+                    {mouseWheelOptions: {interval: 100}}
+                ),
+                new OpenLayers.Control.PanZoom(),
+                new OpenLayers.Control.ArgParser(),
+                new OpenLayers.Control.Attribution()
+            ]} );
+            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
+                    {layers: 'basic'} );
+            map.addLayer(layer);
+            map.zoomToMaxExtent();
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">OpenLayers Mousewheel Interval Example</h1>
+
+    <div id="tags">
+        performance, zoom by wheel
+    </div>
+
+    <div id="shortdesc">Let OpenLayers send less tile requests to the server when wheel-zooming.</div>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+        <p>This example shows how to configure the Navigation control to use 
+        the mousewheel in a less server resource consuming way: as long as you
+        spin the mousewheel, no request will be sent to the server. Instead,
+        the zoomlevel delta will be recorded. After a delay (in this example
+        100ms), a zoom action with the cumulated delta will be performed.</p>
+        <div>
+          <input id="cumulative" type="checkbox" checked="checked"
+                 onchange="setCumulative()"/>
+          <label for="cumulative">Cumulative mode. If this mode is deactivated, 
+            only one zoom event will be performed after the delay.</label>
+        </div>
+
+    </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/multimap-mercator.html
===================================================================
--- sandbox/ahocevar/playground/examples/multimap-mercator.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/multimap-mercator.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,7 +12,8 @@
     </style>
 
 
-    <script type="text/javascript" src="http://clients.multimap.com/API/maps/1.1/metacarta_04"></script>
+    <!-- multimap api key for http://(www.)openlayers.org -->
+    <script type="text/javascript" src="http://developer.multimap.com/API/maps/1.2/OA10072915821139765"></script>
 
     <script src="../lib/OpenLayers.js"></script>
     <script type="text/javascript">
@@ -34,11 +35,9 @@
                 {'sphericalMercator': true}
             ); 
             merc = new OpenLayers.Layer.WMS("World Map",
-                                            "http://world.freemap.in/tiles/",
-                                            {'layers': 'factbook-overlay',
-                                             'format':'png'},
-                                            {'reproject': false,
-                                             'opacity': 0.4,
+                                            "http://maps.opengeo.org/geowebcache/service/wms",
+                                            {'layers': 'bluemarble'},
+                                            {'opacity': 0.4,
                                              'isBaseLayer': false,
                                              'wrapDateLine': true});
 
@@ -54,7 +53,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">MultiMap Mercator Example</h3>
+    <h1 id="title">MultiMap Mercator Example</h1>
+    <div id="tags">
+        MultiMap, basic, cleanup
+    </div>
     <p id="shortdesc">
       This sphericalMercator example using multimap demonstrates that the
       multimap layer does not fully support the sphericalMercator projection at

Modified: sandbox/ahocevar/playground/examples/multiserver.html
===================================================================
--- sandbox/ahocevar/playground/examples/multiserver.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/multiserver.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,8 +13,8 @@
         function init(){
             map = new OpenLayers.Map( 'map' );
             
-            var urlArray = ["http://t1.labs.metacarta.com/wms-c/Basic.py",
-                            "http://t2.labs.metacarta.com/wms-c/Basic.py"];
+            var urlArray = ["http://tilecache.osgeo.org/wms-c/Basic.py",
+                            "http://tilecache.osgeo.org/wms-c/Basic.py"];
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
                                               urlArray,
                                               {layers: 'basic'} );
@@ -27,6 +27,7 @@
     <h1 id="title">Multiple Server URLS</h1>
 
   <div id="tags">
+    performance, multiple urls, request
   </div>
   <p id="shortdesc">
       Load your tiles faster by pointing to the same server, but with different urls

Modified: sandbox/ahocevar/playground/examples/mvs.html
===================================================================
--- sandbox/ahocevar/playground/examples/mvs.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/mvs.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -17,7 +17,7 @@
 function runMVS() {
     OpenLayers.ProxyHost = '/proxy/?url='; 
     if (document.location.protocol != "file:") {
-        theArgs = OpenLayers.Util.getArgs();
+        theArgs = OpenLayers.Util.getParameters();
     } else {
         theArgs = {};
         theArgs.center = "0,0";
@@ -81,7 +81,7 @@
             case 'openlayers':
                 theMVS.addLayer(
                   new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                        "http://labs.metacarta.com/wms/vmap0", 
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0", 
                         {layers: 'basic'} )
                   );
                 break;

Modified: sandbox/ahocevar/playground/examples/navigation-control.html
===================================================================
--- sandbox/ahocevar/playground/examples/navigation-control.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/navigation-control.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,7 @@
         function init(){
             map = new OpenLayers.Map( 'map', { controls: [] });
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
             map.addLayer(layer);
             nav = new OpenLayers.Control.Navigation({'zoomWheelEnabled': false});
@@ -21,7 +21,9 @@
   <body onload="init()">
     <h1 id="title">Navigation Control</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        drag, move, zoom, navigate
+    </div>
 
     <div id="shortdesc">Demonstrate Navigation Control features</div>
 

Modified: sandbox/ahocevar/playground/examples/navigation-history.html
===================================================================
--- sandbox/ahocevar/playground/examples/navigation-history.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/navigation-history.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,7 +32,7 @@
                 
                 var layer = new OpenLayers.Layer.WMS(
                     "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'}
                 );
                 map.addLayer(layer);
@@ -44,6 +44,7 @@
         <h1 id="title">Map Navigation History Example</h1>
 
         <div id="tags">
+            history, basic
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/navtoolbar-alwaysZoom.html
===================================================================
--- sandbox/ahocevar/playground/examples/navtoolbar-alwaysZoom.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/navtoolbar-alwaysZoom.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -56,7 +56,7 @@
 
 	            var wms = new OpenLayers.Layer.WMS(
 	                "OpenLayers WMS",
-	                "http://labs.metacarta.com/wms/vmap0",
+	                "http://vmap0.tiles.osgeo.org/wms/vmap0",
 	                {layers: 'basic'}
 	            );					  
 								
@@ -70,6 +70,9 @@
 	</head>
 	<body onload="init()">
 		<h1 id="title">A navToolbar with an alwaysZoom ZoomBox</h1>
+        <div id="tags">
+            navigation toolbar
+        </div>
 		<p id="shortdesc">
        		Demo of a custom NavToolbar which uses a zoomBox tool that always zoom in even when the zoom box is too big.
     	</p> 

Modified: sandbox/ahocevar/playground/examples/navtoolbar-outsidemap.html
===================================================================
--- sandbox/ahocevar/playground/examples/navtoolbar-outsidemap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/navtoolbar-outsidemap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -22,7 +22,7 @@
         function init(){
             map = new OpenLayers.Map( 'map', { controls: [new OpenLayers.Control.PanZoom()] } );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             var panel = new OpenLayers.Control.NavToolbar({'div':OpenLayers.Util.getElement('paneldiv')});
             map.addControl(panel);
@@ -33,6 +33,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Navigation Toolbar: Outside the Map</h1>
+    <div id="tags">
+        navigation toolbar, style, position, div
+    </div>
     <div id="map" class="smallmap"></div>
     <div id="paneldiv" class="olControlNavToolbar"></div>
     <div id="docs">

Modified: sandbox/ahocevar/playground/examples/navtoolbar.html
===================================================================
--- sandbox/ahocevar/playground/examples/navtoolbar.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/navtoolbar.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -18,7 +18,7 @@
         function init() {
             map = new OpenLayers.Map( 'map', { controls: [new OpenLayers.Control.PanZoom()] } );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
 
             var panel = new OpenLayers.Control.NavToolbar();
@@ -29,7 +29,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">NavToolbar Demo</h3>
+    <h1 id="title">NavToolbar Demo</h1>
+    <div id="tags">
+        navigation toolbar, basic
+    </div>
     <p id="shortdesc">
        Demo the NavToolbar, a subclass of Control.Panel which shows icons for
        navigation.

Modified: sandbox/ahocevar/playground/examples/ordering.html
===================================================================
--- sandbox/ahocevar/playground/examples/ordering.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/ordering.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -168,6 +168,7 @@
         <h1 id="title">Z-Index/Y-Order Example</h1>
 
         <div id="tags">
+            stack, stacking, zindex, ordering
         </div>
 
         <p id="shortdesc">

Copied: sandbox/ahocevar/playground/examples/osm-google.html (from rev 10919, trunk/openlayers/examples/osm-google.html)
===================================================================
--- sandbox/ahocevar/playground/examples/osm-google.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/osm-google.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers OSM and Google Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="osm-google.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">OSM and Google Together</h1>
+        <p id="shortdesc">
+            Demonstrate use of an OSM layer and a Google layer as base layers.
+        </p>
+        <div id="tags">
+            openstreetmap google
+        </div>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                The Google(v3) layer and the OSM are both in the same projection
+                - spherical mercator - and can be used on a map together.
+                See the <a href="osm-google.js" target="_blank">
+                osm-google.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/osm-google.js (from rev 10919, trunk/openlayers/examples/osm-google.js)
===================================================================
--- sandbox/ahocevar/playground/examples/osm-google.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/osm-google.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,28 @@
+var map;
+
+function init() {
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: new OpenLayers.Projection("EPSG:900913"),
+        units: "m",
+        maxResolution: 156543.0339,
+        maxExtent: new OpenLayers.Bounds(
+            -20037508, -20037508, 20037508, 20037508.34
+        )
+    });
+    
+    var osm = new OpenLayers.Layer.OSM();            
+    var gmap = new OpenLayers.Layer.Google("Google Streets");
+    
+    map.addLayers([osm, gmap]);
+
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+    map.setCenter(
+        new OpenLayers.LonLat(10.2, 48.9).transform(
+            new OpenLayers.Projection("EPSG:4326"),
+            map.getProjectionObject()
+        ), 
+        5
+    );
+}

Modified: sandbox/ahocevar/playground/examples/osm-layer.html
===================================================================
--- sandbox/ahocevar/playground/examples/osm-layer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/osm-layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -104,6 +104,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Advanced OSM Layer</h1>
+    <div id="tags">
+        openstreetmap advanced
+    </div>
     <div id="map" class="smallmap"></div>
     <div id="download">
       <ul>

Copied: sandbox/ahocevar/playground/examples/osm.html (from rev 10919, trunk/openlayers/examples/osm.html)
===================================================================
--- sandbox/ahocevar/playground/examples/osm.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/osm.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,37 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Basic Single WMS Example</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, layer;
+        function init(){
+            map = new OpenLayers.Map( 'map');
+            layer = new OpenLayers.Layer.OSM( "Simple OSM Map");
+            map.addLayer(layer);
+            map.setCenter(
+                new OpenLayers.LonLat(-71.147, 42.472).transform(
+                    new OpenLayers.Projection("EPSG:4326"),
+                    map.getProjectionObject()
+                ), 12
+            );    
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Basic OSM Example</h1>
+
+    <div id="tags">
+        openstreetmap basic
+    </div>
+
+    <div id="shortdesc">Show a Simple OSM Map</div>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+        This example shows a very simple OSM layout with minimal controls. 
+    </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/outOfRangeMarkers.html
===================================================================
--- sandbox/ahocevar/playground/examples/outOfRangeMarkers.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/outOfRangeMarkers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -50,7 +50,10 @@
 
 
  <body onload="init()">
-    <h3 id="title">Using maxResolution to control overlays</h3>
+    <h1 id="title">Using maxResolution to control overlays</h1>
+    <div id="tags">
+        cleanup
+    </div>
     <p id="shortdesc">
       See how to control the maximum resolution for a markers layer, 
       causing it to not be displayed beyond a certain point.

Modified: sandbox/ahocevar/playground/examples/overviewmap.html
===================================================================
--- sandbox/ahocevar/playground/examples/overviewmap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/overviewmap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,6 +21,7 @@
         <h1 id="title">Overview Map</h1>
 
         <div id="tags">
+            overview, mapOptions, basic
         </div>
         <p id="shortdesc">
             Enable a small Overview Map that moves/interacts with your main map.
@@ -32,17 +33,17 @@
         <div id="map2"></div>
         <p>The second map has an overview map control that is created with
         non-default options.  In this case, the mapOptions property of the
-        control has been set to use non-default projection related properties.
-        In addition, any other properties of the overview map control can be
+        control has been set to use non-default projection related properties,
+        and the layers property has been set to use a layer different from the main
+        map. In addition, any other properties of the overview map control can be
         set in this way.</p>
         <script defer="defer" type="text/javascript">
         
-        // create the top map (with default overview map control)
-        var map1 = new OpenLayers.Map('map1');
+        // set up some layers
         
         var ol = new OpenLayers.Layer.WMS(
             "OpenLayers WMS", 
-            "http://labs.metacarta.com/wms/vmap0",
+            "http://vmap0.tiles.osgeo.org/wms/vmap0",
             {layers: 'basic'}
         );
         
@@ -52,54 +53,64 @@
             {layers: "landsat7"}
         );
         
+        // A clone of the above layer that we will use as overview for map2.
+        // We need to clone jpl before the it gets added to a map, so the
+        // clone can have its own maxExtent and maxResolution instead of
+        // getting these settings initialized from map1.
+        var jplOverview = jpl.clone();
+        
+        // A more detailled layer of Manhattan for map2
+        var ny = new OpenLayers.Layer.WMS(
+            "Manhattan", 
+            "http://demo.opengeo.org/geoserver/wms",
+            {
+                layers: 'tiger-ny', 
+                format: 'image/png'
+            }
+        );
+        
+        // create the top map (with default overview map control)
+        var map1 = new OpenLayers.Map('map1');
+        
         map1.addLayers([ol, jpl]);
         map1.addControl(new OpenLayers.Control.LayerSwitcher());
         
         // create an overview map control with the default options
-        var overview1 = new OpenLayers.Control.OverviewMap();
+        var overview1 = new OpenLayers.Control.OverviewMap({
+            maximized: true
+        });
         map1.addControl(overview1);
         
         map1.setCenter(new OpenLayers.LonLat(0, 0), 2);
         
-        // expand the overview map control
-        overview1.maximizeControl();
-        
-        
         // create the bottom map (with advanced overview map control)
         var mapOptions = {
-            maxExtent: new OpenLayers.Bounds(33861, 717605, 330846, 1019656), 
-            maxResolution: 296985/1024,
-            projection: "EPSG:2805",
+            maxExtent: new OpenLayers.Bounds(-8242894.927728, 4965204.031195,
+                    -8227290.161511, 4994963.723637), 
+            maxResolution: 116.24879860156216,
+            projection: "EPSG:900913",
             units: "m"
         };
 
         var map2 = new OpenLayers.Map('map2', mapOptions);
         
-        var bos = new OpenLayers.Layer.WMS(
-            "Boston", 
-            "http://boston.freemap.in/cgi-bin/mapserv",
-            {
-                map: '/www/freemap.in/boston/map/gmaps.map', 
-                layers: 'border,water,roads,rapid_transit,buildings', 
-                format: 'png'
-            }
-        );
+        map2.addLayers([ny]);
         
-        map2.addLayers([bos]);
-        map2.addControl(new OpenLayers.Control.LayerSwitcher());
-        
         // create an overview map control with non-default options
         var controlOptions = {
-            mapOptions: mapOptions
+            maximized: true,
+            mapOptions: OpenLayers.Util.extend(mapOptions, {
+                maxResolution: 156543.0339,
+                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
+                                     20037508.34, 20037508.34)
+            }),
+            layers: [jplOverview]
         }
         var overview2 = new OpenLayers.Control.OverviewMap(controlOptions);
         map2.addControl(overview2);
         
-        map2.setCenter(new OpenLayers.LonLat(182500, 868500), 3);
+        map2.setCenter(new OpenLayers.LonLat(-8233165.3575055, 4980298.21113769), 3);
         
-        // expand the overview map control
-        overview2.maximizeControl();
-
         </script>
     </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/pan-zoom-panels.html
===================================================================
--- sandbox/ahocevar/playground/examples/pan-zoom-panels.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/pan-zoom-panels.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,7 +32,7 @@
         
         var wms = new OpenLayers.Layer.WMS(
             "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0",
+            "http://vmap0.tiles.osgeo.org/wms/vmap0",
             {layers: 'basic'}
         );
         map.addLayers([wms]);
@@ -40,11 +40,49 @@
         map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
     }
     </script>
+    <style type="text/css">
+        .olControlPanPanel {
+             width: 100%;
+             height: 100%;
+             left: 0;
+             top: 0;
+        }
+        .olControlPanPanel .olControlPanNorthItemInactive {
+             left: 50%;
+             margin-left: -9px;
+             top: 0;
+        }
+        .olControlPanPanel .olControlPanSouthItemInactive {
+             left: 50%;
+             margin-left: -9px;
+             top: auto;
+             bottom: 0;
+        }
+        .olControlPanPanel .olControlPanWestItemInactive {
+             top: 50%;
+             margin-top: -9px;
+             left: 0;
+        }
+        .olControlPanPanel .olControlPanEastItemInactive {
+             top: 50%;
+             margin-top: -9px;
+             left: auto;
+             right: 0;
+        }
+       .olControlZoomPanel {
+             left: auto;
+             right: 23px;
+             top: 8px;
+       } 
+    </style>
 </head>
 <body onload='init();'>
     <h1 id="title">Pan and Zoom Panels</h1>
-    <div id="tags"></div>
-    <p id="shortdesc">Customizable pan and zoom panels</p>
+    <div id="tags">
+        panning, zooming, panel, CSS, style
+    </div>
+    <p id="shortdesc">
+    Customizable pan and zoom panels
     </p>
     <div id="map" class="smallmap"></div>
     <p id="docs">

Modified: sandbox/ahocevar/playground/examples/panel.html
===================================================================
--- sandbox/ahocevar/playground/examples/panel.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/panel.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,7 @@
           width:  24px;
           height: 24px;
           margin: 5px;
-          background-color:red;
+          background-color:white;
         }
         
         .olControlPanel .olControlMouseDefaultsItemActive { 
@@ -60,7 +60,7 @@
         function init(){
             map = new OpenLayers.Map( 'map', { controls: [] } );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
 
             vlayer = new OpenLayers.Layer.Vector( "Editable" );
@@ -78,6 +78,12 @@
                     {title:'Draw a feature'}),
                 new OpenLayers.Control.ZoomToMaxExtent({title:"Zoom to the max extent"}) 
             ]);
+            
+            nav = new OpenLayers.Control.NavigationHistory();
+            // parent control must be added to the map
+            map.addControl(nav);
+            panel.addControls([nav.next, nav.previous]);
+            
             map.addControl(panel);
 
             map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
@@ -85,7 +91,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">Custom Control.Panel</h3>
+    <h1 id="title">Custom Control.Panel</h1>
+    <div id="tags">
+        panels, CSS, style, basic
+    </div>
     <p id="shortdesc">
       Create a custom control.panel, styled entirely with
       CSS, and add your own controls to it.

Modified: sandbox/ahocevar/playground/examples/point-track-markers.html
===================================================================
--- sandbox/ahocevar/playground/examples/point-track-markers.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/point-track-markers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
         function init(){
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             map.setCenter(new OpenLayers.LonLat(20.22, 22.05), 9);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
@@ -53,7 +53,11 @@
   </head>
   <body onload="init()">
     <h1 id="title">GeoRSS PointTrack in OpenLayers</h1>
-    <p style="font-size:.9em;">This demo uses OpenLayers.Layer.GeoRSS and OpenLayers.Layer.PointTrack. The track is created by connecting the points of the GeoRSS feed.</a></p>
+    <div id="tags">
+        GeoRSS, PointTrack
+    </div>
+    <p id="shortdesc">This demo uses OpenLayers.Layer.GeoRSS and OpenLayers.Layer.PointTrack.</p>
+    <p style="font-size:.9em;">The track is created by connecting the points of the GeoRSS feed.</a></p>
     <form onsubmit="return false;">
    GeoRSS URL: <input type="text" id="url" size="50" /><input type="submit" onclick="addUrl(); return false;" value="Load Feed" onsubmit="addUrl(); return false;" />
     </form>  

Modified: sandbox/ahocevar/playground/examples/popupMatrix.html
===================================================================
--- sandbox/ahocevar/playground/examples/popupMatrix.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/popupMatrix.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -870,6 +870,7 @@
   <h1 id="title">Popup Matrix</h1>
 
   <div id="tags">
+  popup, popups
   </div>
       <p id="shortdesc">
           All kinds of different popup configurations.


Property changes on: sandbox/ahocevar/playground/examples/popupMatrix.jpg
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/examples/popups.html
===================================================================
--- sandbox/ahocevar/playground/examples/popups.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/popups.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             layer = new OpenLayers.Layer.Google( "Google" );
             map.addLayer(layer);
@@ -108,6 +108,7 @@
   <h1 id="title">Popup Mayhem</h1>
 
   <div id="tags">
+    popup, popups
   </div>
   <p id="shortdesc">
       All kinds of ways to create and interact with Popups.

Modified: sandbox/ahocevar/playground/examples/projected-map.html
===================================================================
--- sandbox/ahocevar/playground/examples/projected-map.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/projected-map.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -56,6 +56,7 @@
   <h1 id="title">Layer Projections</h1>
 
   <div id="tags">
+    projection, reprojection, epsg, basic
   </div>
   <p id="shortdesc">
       Use different (not default) projections with your map 

Modified: sandbox/ahocevar/playground/examples/protocol-gears.html
===================================================================
--- sandbox/ahocevar/playground/examples/protocol-gears.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/protocol-gears.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -31,7 +31,7 @@
 
             // create base layer
             var layer = new OpenLayers.Layer.WMS("OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {"layers": "basic"}
             );
             map.addLayer(layer);
@@ -218,6 +218,7 @@
     <h1 id="title">Gears Protocol Example</h1>
 
     <div id="tags">
+        Google, Gears
     </div>
     <p id="shortdesc">
         Shows the usage of the Gears protocol.

Modified: sandbox/ahocevar/playground/examples/proxy.cgi
===================================================================
--- sandbox/ahocevar/playground/examples/proxy.cgi	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/proxy.cgi	2010-11-28 15:48:59 UTC (rev 10920)
@@ -19,7 +19,9 @@
                 'labs.metacarta.com', 'world.freemap.in', 
                 'prototype.openmnnd.org', 'geo.openplans.org',
                 'sigma.openplans.org', 'demo.opengeo.org',
-                'www.openstreetmap.org', 'sample.avencia.com']
+                'www.openstreetmap.org', 'sample.azavea.com',
+                'v2.suite.opengeo.org', 'v-swe.uni-muenster.de:8080', 
+                'vmap0.tiles.osgeo.org']
 
 method = os.environ["REQUEST_METHOD"]
 

Modified: sandbox/ahocevar/playground/examples/regular-polygons.html
===================================================================
--- sandbox/ahocevar/playground/examples/regular-polygons.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/regular-polygons.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -28,16 +28,20 @@
             margin-left: 15em;
             position: absolute;
         }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
     </style>
     <script src="../lib/OpenLayers.js"></script>
     <script type="text/javascript">
         var map, polygonControl;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
         function init(){
             map = new OpenLayers.Map('map');
             
             var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}); 
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'}); 
 
             var polygonLayer = new OpenLayers.Layer.Vector("Polygon Layer");
 
@@ -68,7 +72,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h2 id="title">OpenLayers Regular Polygon Example</h2>
+    <h1 id="title">OpenLayers Regular Polygon Example</h1>
+    <div id="tags">
+        vector, feature, regularpolygon, drawing, draw, advanced
+    </div>     
     <p id="shortdesc">
       Shows how to use the RegularPolygon handler to draw features with
       different numbers of sides.

Modified: sandbox/ahocevar/playground/examples/resize-features.html
===================================================================
--- sandbox/ahocevar/playground/examples/resize-features.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/resize-features.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -15,7 +15,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             
             var style_blue = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
@@ -79,7 +79,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">Resize Features Programatically</h3>
+    <h1 id="title">Resize Features Programatically</h1>
+    <div id="tags">
+        vector, feature, resizing, resize
+    </div>    
     <p id="shortdesc">
       Demonstration of how to use the geometry resize methods to
       change feature sizes programatically.

Modified: sandbox/ahocevar/playground/examples/restricted-extent.html
===================================================================
--- sandbox/ahocevar/playground/examples/restricted-extent.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/restricted-extent.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -17,7 +17,7 @@
 
             var wms = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0?",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                 {layers: 'basic'}
             ); 
 
@@ -36,7 +36,10 @@
     </script>
   </head>
   <body onload="init()">
-    <h3 id="title">OpenLayers Restricted Extent Example</h3>
+    <h1 id="title">OpenLayers Restricted Extent Example</h1>
+    <div id="tags">
+        map, restrict, restrictedextent, extent
+    </div>    
     <p id="shortdesc">
       Don't let users drag outside the map extent: instead, limit dragging such
       that the extent of the layer is the maximum viewable area.

Modified: sandbox/ahocevar/playground/examples/rotate-features.html
===================================================================
--- sandbox/ahocevar/playground/examples/rotate-features.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/rotate-features.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -15,7 +15,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             
             var style_blue = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
@@ -94,8 +94,9 @@
   <body onload="init()">
     <h1 id="title">Rotate vector features</h1>
 
-  <div id="tags">
-  </div>
+    <div id="tags">
+        vector, feature, rotating, rotation, rotate, advanced
+    </div>
   <p id="shortdesc">
       Details on how to create and rotate vector features programmatically
   </p>

Modified: sandbox/ahocevar/playground/examples/select-feature-multilayer.html
===================================================================
--- sandbox/ahocevar/playground/examples/select-feature-multilayer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/select-feature-multilayer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
             map = new OpenLayers.Map('map');
             var wmsLayer = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             ); 
 
@@ -106,6 +106,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Select Feature on Multiple Layers Example</h1>
+    <div id="tags">
+        vector, feature, selecting, selection, advanced
+    </div>     
     <p id="shortdesc">
       Select a feature on click with the Control.SelectFeature on multiple 
       vector layers.

Modified: sandbox/ahocevar/playground/examples/select-feature-openpopup.html
===================================================================
--- sandbox/ahocevar/playground/examples/select-feature-openpopup.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/select-feature-openpopup.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,7 +32,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}); 
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'}); 
 
             var polygonLayer = new OpenLayers.Layer.Vector("Polygon Layer");
 
@@ -71,6 +71,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Open Popup on Layer.Vector</h1> 
+    <div id="tags">
+        vector, feature, selecting, selection, popup
+    </div>    
     <p id="shortdesc">
       Using a Control.SelectFeature, open a popup on click.
     </p>

Modified: sandbox/ahocevar/playground/examples/select-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/select-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/select-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,11 +16,20 @@
             map = new OpenLayers.Map('map');
             var wmsLayer = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             ); 
 
             var vectors = new OpenLayers.Layer.Vector("Vector Layer");
+            vectors.events.on({
+                'featureselected': function(feature) {
+                    $('counter').innerHTML = this.selectedFeatures.length;
+                },
+                'featureunselected': function(feature) {
+                    $('counter').innerHTML = this.selectedFeatures.length;
+                }
+            });
+
             map.addLayers([wmsLayer, vectors]);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
             
@@ -74,17 +83,26 @@
 
         function update() {
             var clickout = document.getElementById("clickout").checked;
-            drawControls.select.clickout = clickout;
-            drawControls.select.box = document.getElementById("box").checked;
-            if(drawControls.select.active) {
-                drawControls.select.deactivate();
-                drawControls.select.activate();
+            if(clickout != drawControls.select.clickout) {
+                drawControls.select.clickout = clickout;
             }
+
+            var box = document.getElementById("box").checked;
+            if(box != drawControls.select.box) {
+                drawControls.select.box = box;
+                if(drawControls.select.active) {
+                    drawControls.select.deactivate();
+                    drawControls.select.activate();
+                }
+            }
         }
     </script>
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Select Feature Example</h1>
+    <div id="tags">
+        vector, feature, selecting, selection, advanced
+    </div>        
     <p id="shortdesc">
       Select a feature on hover or click with the Control.SelectFeature on a
       vector layer.
@@ -119,7 +137,7 @@
         <li>
             <input type="radio" name="type" value="select" id="selectToggle"
                    onclick="toggleControl(this);" />
-            <label for="selectToggle">select feature</label>
+            <label for="selectToggle">select feature (<span id="counter">0</span> features selected)</label>
             <ul>
                 <li>
                     <input id="box" type="checkbox" checked="checked"

Modified: sandbox/ahocevar/playground/examples/setextent.html
===================================================================
--- sandbox/ahocevar/playground/examples/setextent.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/setextent.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -7,6 +7,9 @@
 </head>
 <body>
 <h1 id="title">Setting a Visual Extent</h1>
+<div id="tags">
+    boxes, box, marker
+</div>
 <p id='shortdesc'>
   Use a boxes layer to visually display the area of interest indicated by a user.
 </p>
@@ -22,7 +25,7 @@
     var map = new OpenLayers.Map('map');
     var bounds = new OpenLayers.Bounds(-45,-45, 0, 45); 
     var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+        "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
     map.addLayer(wms);
     map.zoomToExtent(bounds);
     var boxes = new OpenLayers.Layer.Boxes("boxes");

Copied: sandbox/ahocevar/playground/examples/single-tile.html (from rev 10919, trunk/openlayers/examples/single-tile.html)
===================================================================
--- sandbox/ahocevar/playground/examples/single-tile.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/single-tile.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers: Single Tile</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+    </head>
+    <body>
+        <h1 id="title">Single Tile Example</h1>
+        <div id="tags">tile, ratio, singleTile, performance</div>
+        <p id="shortdesc">
+            Use the singleTile option on gridded layers to request a single tile.
+        </p>  
+        <div id="mapDiv" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                This map demonstrates the use of the singleTile property as an
+                alternative to the default tiled behavior of layers.  The first
+                layer in the map is a WMS layer with the singleTile option set
+                true.  The second layer is a WMS layer with the default options.
+            </p>
+            <p>
+                View the <a href="single-tile.js" target="_blank">single-tile.js</a>
+                source to see how this is done.
+            </p>
+        </div>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="single-tile.js"></script>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/single-tile.js (from rev 10919, trunk/openlayers/examples/single-tile.js)
===================================================================
--- sandbox/ahocevar/playground/examples/single-tile.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/single-tile.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,20 @@
+var map = new OpenLayers.Map({
+    div: "mapDiv",
+    layers: [
+        new OpenLayers.Layer.WMS(
+            "Single Tile", 
+            "http://vmap0.tiles.osgeo.org/wms/vmap0",
+            {layers: "basic"}, 
+            {singleTile: true, ratio: 1}
+        ), 
+        new OpenLayers.Layer.WMS(
+            "Multiple Tiles", 
+            "http://vmap0.tiles.osgeo.org/wms/vmap0",
+            {layers: "basic"}
+        )
+    ],
+    center: new OpenLayers.LonLat(6.5, 40.5),
+    zoom: 4
+});
+
+map.addControl(new OpenLayers.Control.LayerSwitcher());

Copied: sandbox/ahocevar/playground/examples/sld-parser.html (from rev 10919, trunk/openlayers/examples/sld-parser.html)
===================================================================
--- sandbox/ahocevar/playground/examples/sld-parser.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/sld-parser.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers SLD Parser</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <style>
+            #input {
+                width: 90%;
+                height: 300px;
+            }
+            #output {
+                width: 90%;
+                height: 300px;
+            }
+        </style>
+    </head>
+    <body>
+        <h1 id="title">SLD Parser</h1>
+        <div id="tags">
+            sld, sldselect, styling, style, parser, cleanup
+        </div>
+        <div id="shortdesc">Parsing Styled Layer Descriptor (SLD) documents with the SLD format.</div>
+
+        <textarea id="input">paste SLD here</textarea><br>
+        <input type="checkbox" id="symbolizers" checked="checked"><label for="symbolizers">Maintain multiple symbolizers and FeatureTypeStyle elements</label><br>
+        <input type="checkbox" id="array"><label for="array">Compile an array of named styles instead of an object.</label><br>
+        <input type="button" id="button" value="Parse SLD">
+
+        <div id="docs">
+            This example uses the SLD format to parse SLD documents pasted into the textarea above.  
+            A rough representation of the parsed style is shown in the textarea below.
+        </div>
+        
+        <textarea id="output"></textarea>
+        
+        <script>
+        
+            var button = document.getElementById("button");
+            var input = document.getElementById("input");
+            var output = document.getElementById("output");
+            var symbolizers = document.getElementById("symbolizers");
+            var array = document.getElementById("array");
+            
+            var json = new OpenLayers.Format.JSON();
+
+            var format, obj;
+            
+            button.onclick = function() {
+                var str = input.value;
+                format = new OpenLayers.Format.SLD({
+                    multipleSymbolizers: !!symbolizers.checked,
+                    namedLayersAsArray: !!array.checked
+                });
+                obj = format.read(str);
+                try {
+                    output.value = json.write(obj, true);
+                } catch (err) {
+                    output.value = "Trouble: " + err;
+                }
+            }
+        
+        </script>
+
+    </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/sld.html
===================================================================
--- sandbox/ahocevar/playground/examples/sld.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/sld.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -91,6 +91,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Styled Layer Descriptor (SLD) Example</h1>
+    <div id="tags">
+        vector, feature, sld, styling, style
+    </div>
     <p id="shortdesc">
         Parsing SLD and applying styles to a vector layer.
     </p>


Property changes on: sandbox/ahocevar/playground/examples/small.jpg
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/examples/snap-split.html
===================================================================
--- sandbox/ahocevar/playground/examples/snap-split.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/snap-split.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -232,6 +232,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Snapping & Splitting Example</h1>
+    <div id="tags">
+        vector, feature, splitting, snapping, stylemap, advanced
+    </div>    
     <div id="shortdesc">A demonstration snapping and splitting while editing vector features.</div>
     <div id="map" class="smallmap"></div>
     <br/>

Modified: sandbox/ahocevar/playground/examples/snapping.html
===================================================================
--- sandbox/ahocevar/playground/examples/snapping.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/snapping.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -164,7 +164,7 @@
             });
             draw = new OpenLayers.Control.DrawFeature(
                 poly, OpenLayers.Handler.Polygon,
-                {displayClass: "olControlDrawFeaturePoint", title: "Draw Features"}
+                {displayClass: "olControlDrawFeaturePoint", title: "Draw Features", handlerOptions: {holeModifier: "altKey"}}
             );
             modify = new OpenLayers.Control.ModifyFeature(
                 poly, {displayClass: "olControlModifyFeature", title: "Modify Features"}
@@ -272,6 +272,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Snapping Example</h1>
+    <div id="tags">
+        vector, feature, snapping, stylemap, advanced
+    </div>      
     <div id="shortdesc">A demonstration snapping while editing vector features.</div>
     <div id="map" class="smallmap"></div>
     <br/>

Copied: sandbox/ahocevar/playground/examples/sos.html (from rev 10919, trunk/openlayers/examples/sos.html)
===================================================================
--- sandbox/ahocevar/playground/examples/sos.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/sos.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,183 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <style type="text/css">
+    .sosmap {
+        width: 768px;
+        height: 512px;
+    }
+    </style>
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map;
+
+        OpenLayers.ProxyHost = "proxy.cgi?url=";
+        OpenLayers.Util.extend(OpenLayers.Lang.en,
+            {
+                'SOSClientType': "Type",
+                'SOSClientTime': "Date/time",
+                'SOSClientLastvalue': "Last value"
+            }
+        );
+
+        // Example class on how to put all the OpenLayers SOS pieces together
+        OpenLayers.SOSClient = OpenLayers.Class({
+            url: null,
+            map: null,
+            capsformat: new OpenLayers.Format.SOSCapabilities(),
+            obsformat: new OpenLayers.Format.SOSGetObservation(),
+            initialize: function (options) {
+                OpenLayers.Util.extend(this, options);
+                var params = {'service': 'SOS', 'request': 'GetCapabilities'};
+                var paramString = OpenLayers.Util.getParameterString(params);
+                url = OpenLayers.Util.urlAppend(this.url, paramString);
+                OpenLayers.Request.GET({url: url,
+                    success: this.parseSOSCaps, scope: this});
+            },
+            getFois: function() {
+                var result = [];
+                this.offeringCount = 0; 
+                for (var name in this.SOSCapabilities.contents.offeringList) {
+                    var offering = this.SOSCapabilities.contents.offeringList[name];
+                    this.offeringCount++;
+                    for (var i=0, len=offering.featureOfInterestIds.length; i<len; i++) {
+                        var foi = offering.featureOfInterestIds[i];
+                        if (OpenLayers.Util.indexOf(result, foi) === -1) {
+                            result.push(foi);
+                        }
+                    }
+                }
+                return result;
+            },
+            parseSOSCaps: function(response) {
+                // cache capabilities for future use
+                this.SOSCapabilities = this.capsformat.read(response.responseXML || response.responseText);
+                this.layer = new OpenLayers.Layer.Vector("Stations", {
+                    strategies: [new OpenLayers.Strategy.Fixed()],
+                    protocol: new OpenLayers.Protocol.SOS({
+                        formatOptions: {internalProjection: map.getProjectionObject()},
+                        url: this.url,
+                        fois: this.getFois()
+                    })
+                });
+                this.map.addLayer(this.layer);
+                this.ctrl = new OpenLayers.Control.SelectFeature(this.layer,
+                    {scope: this, onSelect: this.onFeatureSelect});
+                this.map.addControl(this.ctrl);
+                this.ctrl.activate();
+            },
+            getTitleForObservedProperty: function(property) {
+                for (var name in this.SOSCapabilities.contents.offeringList) {
+                    var offering = this.SOSCapabilities.contents.offeringList[name];
+                    if (offering.observedProperties[0] === property) {
+                        return offering.name;
+                    }
+                }
+            },
+            showPopup: function(response) {
+                this.count++;
+                var output = this.obsformat.read(response.responseXML || response.responseText);
+                if (output.measurements.length > 0) {
+                    this.html += '<tr>';
+                    this.html += '<td width="100">'+this.getTitleForObservedProperty(output.measurements[0].observedProperty)+'</td>';
+                    this.html += '<td>'+output.measurements[0].samplingTime.timeInstant.timePosition+'</td>';
+                    this.html += '<td>'+output.measurements[0].result.value + ' ' + output.measurements[0].result.uom + '</td>';
+                    this.html += '</tr>';
+                }
+                // check if we are done
+                if (this.count === this.numRequests) {
+                    var html = '<table cellspacing="10"><tbody>';
+                    html += '<tr>';
+                    html += '<th><b>'+OpenLayers.i18n('SOSClientType')+'</b></th>';
+                    html += '<th><b>'+OpenLayers.i18n('SOSClientTime')+'</b></th>';
+                    html += '<th><b>'+OpenLayers.i18n('SOSClientLastvalue')+'</b></th>';
+                    html += '</tr>';
+                    html += this.html;
+                    html += '</tbody></table>';
+                    var popup = new OpenLayers.Popup.FramedCloud("sensor",
+                    this.feature.geometry.getBounds().getCenterLonLat(),
+                        null,
+                        html,
+                        null,
+                        true,
+                        function(e) {
+                            this.hide();
+                            OpenLayers.Event.stop(e);
+                            // unselect so popup can be shown again
+                            this.map.getControlsByClass('OpenLayers.Control.SelectFeature')[0].unselectAll();
+                        } 
+                    );
+                    this.feature.popup = popup;
+                    this.map.addPopup(popup);
+                }
+            },
+            onFeatureSelect: function(feature) {
+                this.feature = feature;
+                this.count = 0;
+                this.html = '';
+                this.numRequests = this.offeringCount;
+                if (!this.responseFormat) {
+                    for (format in this.SOSCapabilities.operationsMetadata.GetObservation.parameters.responseFormat.allowedValues) {
+                        // look for a text/xml type of format
+                        if (format.indexOf('text/xml') >= 0) {
+                            this.responseFormat = format;
+                        }
+                    }
+                }
+                // do a GetObservation request to get the latest values
+                for (var name in this.SOSCapabilities.contents.offeringList) {
+                    var offering = this.SOSCapabilities.contents.offeringList[name];
+                    var xml = this.obsformat.write({
+                        eventTime: 'latest',
+                        resultModel: 'om:Measurement',
+                        responseMode: 'inline',
+                        procedure: feature.attributes.id,
+                        offering: name,
+                        observedProperties: offering.observedProperties,
+                        responseFormat: this.responseFormat
+                    });
+                    OpenLayers.Request.POST({
+                        url: this.url,
+                        scope: this,
+                        failure: this.showPopup,
+                        success: this.showPopup,
+                        data: xml
+                    });
+                }
+            },
+            destroy: function () {
+            },
+            CLASS_NAME: "OpenLayers.SOSClient"
+        });
+
+        function init(){
+            map = new OpenLayers.Map( 'map' );
+            var baseLayer = new OpenLayers.Layer.WMS("Test Layer", "http://vmap0.tiles.osgeo.org/wms/vmap0?", {
+                layers: "basic"}, {singleTile: true});
+
+            var sos = new OpenLayers.SOSClient({map: map, url: 'http://v-swe.uni-muenster.de:8080/WeatherSOS/sos?'});
+
+            map.addLayers([baseLayer]);
+            map.setCenter(new OpenLayers.LonLat(5, 45), 4);
+            map.addControl( new OpenLayers.Control.LayerSwitcher() );
+            map.addControl( new OpenLayers.Control.MousePosition() );
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">SOS client example</h1>
+
+    <div id="tags">
+        sos, sensor, observation, popup, advanced
+    </div>
+        <p id="shortdesc">
+            Shows how to connect OpenLayers to a Sensor Observation Service (SOS)
+        </p>
+    <div id="map" class="sosmap"></div>
+        <div id="docs">
+        <p>This example uses a vector layer with a Protocol.SOS and a fixed Strategy.
+        </p><p>When clicking on a point feature (the weather stations offered by the SOS), the
+        latest values for all offerings are displayed in a popup.</p>
+        </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/spherical-mercator.html
===================================================================
--- sandbox/ahocevar/playground/examples/spherical-mercator.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/spherical-mercator.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -8,6 +8,11 @@
         #map {
             height: 512px;
         }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
     </style>
 
     <script src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script>
@@ -20,9 +25,8 @@
         // make map available for easy debugging
         var map;
 
-        // avoid pink tiles
+        // increase reload attempts 
         OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
 
         function init(){
             var options = {
@@ -102,7 +106,7 @@
                 "http://world.freemap.in/tiles/",
                 {'layers': 'factbook-overlay', 'format':'png'},
                 {
-                    'opacity': 0.4,
+                    'opacity': 0.4, visibility: false,
                     'isBaseLayer': false,'wrapDateLine': true
                 }
             );
@@ -126,6 +130,7 @@
     <h1 id="title">OpenLayers Spherical Mercator Example</h1>
 
     <div id="tags">
+        spherical, mercator, osm, xyz, google, virtual earth, yahoo, tms, tile
     </div>
     <p id="shortdesc">
         Shows the use of the Spherical Mercator Layers, for overlaying 

Modified: sandbox/ahocevar/playground/examples/split-feature.html
===================================================================
--- sandbox/ahocevar/playground/examples/split-feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/split-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,10 +4,15 @@
         
         <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
         <link rel="stylesheet" href="style.css" type="text/css" />
+        <style>
+            /* avoid pink tiles */
+            .olImageLoadError {
+                background-color: transparent !important;
+            }
+        </style>
         <script src="../lib/OpenLayers.js"></script>
         <script type="text/javascript">
             var map, vectors, split;
-            OpenLayers.Util.onImageLoadErrorColor = "transparent";
             function init(){
                 map = new OpenLayers.Map('map');
 
@@ -88,6 +93,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">OpenLayers Split Feature Example</h1>
+        <div id="tags">
+            vector, feature, splitting, split, stylemap
+        </div>          
         <p id="shortdesc">
             Demonstrates splitting of line features.
         </p>

Modified: sandbox/ahocevar/playground/examples/strategy-bbox.html
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-bbox.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/strategy-bbox.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -51,6 +51,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">BBOX Strategy Example</h1>
+        <div id="tags">
+            vector, feature, stylemap, wfs, bbox, strategy, cleanup
+        </div>    
         <p id="shortdesc">
             Uses a BBOX strategy to request features within a bounding box.
         </p>

Copied: sandbox/ahocevar/playground/examples/strategy-cluster-extended.html (from rev 10919, trunk/openlayers/examples/strategy-cluster-extended.html)
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-cluster-extended.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/strategy-cluster-extended.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Extended clustering example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <style type="text/css">
+            label {
+                cursor: pointer
+            }
+            
+            #wrap {
+                width: 925px;
+                margin: 10px;
+            }
+            
+            #strategy-chooser, #generalinfo, #info {
+                width: 400px;
+                padding: 0;
+                float: right;
+                clear: right;
+                margin-bottom: 4px;
+            }
+            
+            #map {
+                float: left;
+            }
+        </style>
+    </head>
+    <body>
+        <h1 id="title">Extended clustering</h1>
+        <div id="tags">
+            cluster, advanced
+        </div>
+        <p id="shortdesc">
+            Shows the usage of custom classes for a fine grained control about 
+            the clustering behaviour.
+        </p>
+        <div id="wrap">
+            <div id="map" class="smallmap">
+            </div>
+            <div id="strategy-chooser">
+                <p>
+                    Select the desired clustering strategy:
+                </p>
+                <label>
+                    <input type="radio" name="strategy" value="none" id="no-strategy" checked="checked">No strategy
+                </label>
+                <br/>
+                <label>
+                    <input type="radio" name="strategy" value="cluster" id="cluster-strategy">Simple cluster-strategy
+                </label>
+                <br/>
+                <label>
+                    <input type="radio" name="strategy" value="attribute-cluster" id="attributive-cluster-strategy">Attributive cluster-strategy
+                </label>
+                <br/>
+                <label>
+                    <input type="radio" name="strategy" value="rule-cluster" id="rulebased-cluster-strategy">Rulebased cluster-strategy
+                </label>
+            </div>
+            <div id="generalinfo">
+            </div>
+            <div id="info">
+            </div>
+        </div>
+        <div id="docs" style="clear: both; padding-top: 10px">
+            <p>
+                The vectorlayer in this example contains random data with an 
+                attribute "clazz" that can take the values 1, 2, 3 and 4. The  
+                features with clazz = 4 are considered more important than the 
+                others.
+            </p>
+            <p>
+                The radiobuttons on the right of the map control the 
+                cluster strategy to be applied to the features.
+            </p>
+            <ul>
+                <li>
+                    <strong>No strategy</strong>
+                    means that all features are 
+                    rendered, no clustering shall be applied
+                </li>
+                <li>
+                    <strong>Simple cluster-strategy</strong>
+                    applies the cluster 
+                    strategy with default options to the layer. You should notice 
+                    that many of the important features with clazz = 4 are getting
+                    lost, since clustering happens regardless of feature attributes
+                </li>
+                <li>
+                    <strong>Attributive cluster-strategy</strong>
+                    uses a 
+                    customized cluster strategy. This strategy is configured to 
+                    cluster features of the same clazz only. You should be able to see all 
+                    red points (clazz = 4) even though the data is clustered. A 
+                    cluster now contains only features of the same clazz.
+                </li>
+                <li>
+                    <strong>Rulebased cluster-strategy</strong>
+                    uses another 
+                    customized cluster strategy. This strategy is configured to  
+                    cluster features that follow a certain rule only. In this case only  
+                    features with a clazz different from 4 are considered as 
+                    candidates for clustering. That means that usually you have fewer 
+                    clusters on the map, yet all with clazz = 4 are easily 
+                    distinguishable
+                </li>
+            </ul>
+            <p>
+                Hover over the features to get a short infomation about the 
+                feature or cluster of features. 
+            </p>
+        </div>
+        <p>
+            View the <a href="strategy-cluster-extended.js" target="_blank">strategy-cluster-extended.js</a>
+            source to see how this is done.
+        </p>
+        <script type="text/javascript" src="../lib/OpenLayers.js"></script>
+        <script type="text/javascript" src="strategy-cluster-extended.js"></script>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/strategy-cluster-extended.js (from rev 10919, trunk/openlayers/examples/strategy-cluster-extended.js)
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-cluster-extended.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/strategy-cluster-extended.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,247 @@
+/**
+ * Class: OpenLayers.Strategy.AttributeCluster
+ * Strategy for vector feature clustering based on feature attributes.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy.Cluster>
+ */
+OpenLayers.Strategy.AttributeCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
+    /**
+     * the attribute to use for comparison
+     */
+    attribute: null,
+    /**
+     * Method: shouldCluster
+     * Determine whether to include a feature in a given cluster.
+     *
+     * Parameters:
+     * cluster - {<OpenLayers.Feature.Vector>} A cluster.
+     * feature - {<OpenLayers.Feature.Vector>} A feature.
+     *
+     * Returns:
+     * {Boolean} The feature should be included in the cluster.
+     */
+    shouldCluster: function(cluster, feature) {
+        var cc_attrval = cluster.cluster[0].attributes[this.attribute];
+        var fc_attrval = feature.attributes[this.attribute];
+        var superProto = OpenLayers.Strategy.Cluster.prototype;
+        return cc_attrval === fc_attrval && 
+               superProto.shouldCluster.apply(this, arguments);
+    },
+    CLASS_NAME: "OpenLayers.Strategy.AttributeCluster"
+});
+
+/**
+ * Class: OpenLayers.Strategy.RuleCluster
+ * Strategy for vector feature clustering according to a given rule.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy.Cluster>
+ */
+OpenLayers.Strategy.RuleCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
+    /**
+     * the rule to use for comparison
+     */
+    rule: null,
+    /**
+     * Method: shouldCluster
+     * Determine whether to include a feature in a given cluster.
+     *
+     * Parameters:
+     * cluster - {<OpenLayers.Feature.Vector>} A cluster.
+     * feature - {<OpenLayers.Feature.Vector>} A feature.
+     *
+     * Returns:
+     * {Boolean} The feature should be included in the cluster.
+     */
+    shouldCluster: function(cluster, feature) {
+        var superProto = OpenLayers.Strategy.Cluster.prototype;
+        return this.rule.evaluate(cluster.cluster[0]) &&
+               this.rule.evaluate(feature) &&
+               superProto.shouldCluster.apply(this, arguments);
+    },
+    CLASS_NAME: "OpenLayers.Strategy.RuleCluster"
+});
+
+
+// global variables
+var map, vectorlayer, features, stylemap, select;
+
+// wrap the instanciation code in an anonymous function that gets executed
+// immeadeately
+(function(){
+
+    // The function that gets called on feature selection: shows information 
+    // about the feature/cluser in a div on the page 
+	var showInformation = function(evt){
+        var feature = evt.feature;
+		var info = 'Last hovered feature:<br>';
+		if (feature.cluster) {
+			info += '&nbsp;&nbsp;Cluster of ' + feature.attributes.count + ' features:';
+			var clazzes = {
+				'1': 0,
+				'2': 0,
+				'3': 0,
+				'4': 0
+			};
+			for (var i = 0; i < feature.attributes.count; i++) {
+				var feat = feature.cluster[i];
+				clazzes[feat.attributes.clazz]++;
+			}
+			for (var j=1; j<=4; j++) {
+				var plural_s = (clazzes[j] !== 1) ? 's' : '';
+				info += '<br>&nbsp;&nbsp;&nbsp;&nbsp;&bull;&nbsp;clazz ' + j + ': ' + clazzes[j] + ' feature' + plural_s;
+			}
+		} else {
+			info += '&nbsp;&nbsp;Single feature of clazz = ' + feature.attributes.clazz;
+		}
+		$('info').innerHTML = info;
+    };
+
+	// The function that gets called on feature selection. Shows information 
+    // about the number of "points" on the map.
+	var updateGeneralInformation = function() {
+		var info = 'Currently ' + vectorlayer.features.length + ' points are shown on the map.';
+		$('generalinfo').innerHTML = info;
+	};
+	
+	// instanciate the map
+	map = new OpenLayers.Map("map");
+    
+	// background WMS
+    var ol_wms = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", {
+        layers: "basic"
+    });
+    
+	// context to style the vectorlayer
+    var context = {
+        getColor: function(feature){
+            var color = '#aaaaaa';
+			if (feature.attributes.clazz && feature.attributes.clazz === 4) {
+				color = '#ee0000';
+			} else if(feature.cluster) {
+				var onlyFour = true;
+				for (var i = 0; i < feature.cluster.length; i++) {
+					if (onlyFour && feature.cluster[i].attributes.clazz !== 4) {
+						onlyFour = false;
+					}
+				}
+				if (onlyFour === true) {
+					color = '#ee0000';
+				}
+			}
+			return color;
+        }
+    };
+	
+    // style the vectorlayer
+    stylemap = new OpenLayers.StyleMap({
+        'default': new OpenLayers.Style({
+            pointRadius: 5,
+            fillColor: "${getColor}",
+            fillOpacity: 0.7,
+            strokeColor: "#666666",
+            strokeWidth: 1,
+            strokeOpacity: 1,
+			graphicZIndex: 1
+        }, {
+            context: context
+        }),
+		'select' : new OpenLayers.Style({
+            pointRadius: 5,
+            fillColor: "#ffff00",
+            fillOpacity: 1,
+            strokeColor: "#666666",
+            strokeWidth: 1,
+            strokeOpacity: 1,
+			graphicZIndex: 2
+        })
+    });
+    
+    // the vectorlayer
+    vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: []});
+    
+	// the select control
+	select = new OpenLayers.Control.SelectFeature(
+        vectorlayer, {hover: true}
+    );
+    map.addControl(select);
+    select.activate();
+    vectorlayer.events.on({"featureselected": showInformation});
+	
+    map.addLayers([ol_wms, vectorlayer]);
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.zoomToMaxExtent();
+    
+    features = [];
+    // adding lots of features:
+    for (var i = 0; i < 700; i++) {
+        var r1 = Math.random();
+        var r2 = Math.random();
+        var r3 = Math.random();
+        var r4 = Math.random();
+        var px = r1 * 180 * ((r2 < 0.5) ? -1 : 1); 
+        var py = r3 * 90 * ((r4 < 0.5) ? -1 : 1);
+        var p = new OpenLayers.Geometry.Point(px, py);
+        var clazz = (i % 10 === 0) ? 4 : Math.ceil(r4 * 3);
+        var f = new OpenLayers.Feature.Vector(p, {clazz: clazz});
+        features.push(f);
+    }
+    vectorlayer.addFeatures(features);
+    updateGeneralInformation();
+
+    // the behaviour and methods for the radioboxes    
+    var changeStrategy = function() {
+        var strategies = [];
+        // this is the checkbox
+        switch(this.value) {
+            case 'cluster':
+                // standard clustering
+				strategies.push(new OpenLayers.Strategy.Cluster());
+                break;
+            case 'attribute-cluster':
+                // use the custom class: only cluster features of the same clazz
+				strategies.push(new OpenLayers.Strategy.AttributeCluster({
+                    attribute:'clazz'
+                }));
+                break;
+            case 'rule-cluster':
+                // use the custom class: only cluster features that have a 
+				// clazz smaller than 4
+				strategies.push(new OpenLayers.Strategy.RuleCluster({
+                    rule: new OpenLayers.Rule({
+                        filter: new OpenLayers.Filter.Comparison({
+                            type: OpenLayers.Filter.Comparison.LESS_THAN,
+                            property: "clazz",
+                            value: 4
+                        })
+                    })
+                }));
+                break;
+        }
+		// remove layer and control
+        map.removeLayer(vectorlayer);
+		map.removeControl(select);
+		// rebuild layer
+        vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: strategies});
+        map.addLayer( vectorlayer );
+        vectorlayer.addFeatures(features);
+        // rebuild select control
+		select = new OpenLayers.Control.SelectFeature(
+	        vectorlayer, {hover: true}
+	    );
+	    map.addControl(select);
+	    select.activate();
+	    vectorlayer.events.on({"featureselected": showInformation});
+		// update meta information
+		updateGeneralInformation();
+    };
+	// bind the behviour to the radios
+    var inputs = document.getElementsByTagName('input');
+    for( var cnt = 0; cnt < inputs.length; cnt++) {
+      var input = inputs[cnt];
+      if (input.name === 'strategy') {
+         input.onclick = changeStrategy;
+      }
+    }
+})();

Modified: sandbox/ahocevar/playground/examples/strategy-cluster-threshold.html
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-cluster-threshold.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/strategy-cluster-threshold.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -34,9 +34,9 @@
             function init() {
                 map = new OpenLayers.Map('map');
                 var base = new OpenLayers.Layer.WMS("OpenLayers WMS", 
-                    ["http://t3.labs.metacarta.com/wms-c/Basic.py",
-                     "http://t2.labs.metacarta.com/wms-c/Basic.py",
-                     "http://t1.labs.metacarta.com/wms-c/Basic.py"], 
+                    ["http://t3.tilecache.osgeo.org/wms-c/Basic.py",
+                     "http://t2.tilecache.osgeo.org/wms-c/Basic.py",
+                     "http://t1.tilecache.osgeo.org/wms-c/Basic.py"], 
                     {layers: 'satellite'}
                 );
 
@@ -116,6 +116,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">Cluster Strategy Threshold</h1>
+        <div id="tags">
+            vector, feature, stylemap, wfs, cluster, strategy, cleanup
+        </div>         
         <p id="shortdesc">
             Demonstrates the use of the cluster strategy threshold property.
         </p>

Modified: sandbox/ahocevar/playground/examples/strategy-cluster.html
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-cluster.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/strategy-cluster.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -66,7 +66,6 @@
         <script src="animator.js"></script>
         <script type="text/javascript">
             var map, template;
-            var Jugl = window["http://jugl.tschaub.net/trunk/lib/Jugl.js"];
             OpenLayers.ProxyHost = (window.location.host == "localhost") ?
                 "/cgi-bin/proxy.cgi?url=" : "proxy.cgi?url=";
 
@@ -135,7 +134,7 @@
                 map.setCenter(new OpenLayers.LonLat(0, 0), 1);
                 
                 // template setup
-                template = new Jugl.Template("template");
+                template = new jugl.Template("template");
 
             }
             
@@ -168,6 +167,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">Cluster Strategy Example</h1>
+        <div id="tags">
+            vector, feature, stylemap, wfs, cluster, strategy, cleanup
+        </div>         
         <p id="shortdesc">
             Uses a cluster strategy to render points representing clusters of features.
         </p>

Modified: sandbox/ahocevar/playground/examples/strategy-paging.html
===================================================================
--- sandbox/ahocevar/playground/examples/strategy-paging.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/strategy-paging.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -61,6 +61,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">Paging Strategy Example</h1>
+        <div id="tags">
+            vector, feature, stylemap, wfs, paging, strategy, cleanup
+        </div>        
         <p id="shortdesc">
             Uses a paging strategy to cache large batches of features and render a page at a time.
         </p>

Copied: sandbox/ahocevar/playground/examples/style-rules.html (from rev 10919, trunk/openlayers/examples/style-rules.html)
===================================================================
--- sandbox/ahocevar/playground/examples/style-rules.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/style-rules.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,45 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>OpenLayers Rule Based Style</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="style-rules.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">Rule Based Style</h1>
+        <div id="tags">
+            vector, feature, stylemap, filter, comparison
+        </div>        
+        <p id="shortdesc">
+            Use rule based styling to use different symbolizers for different
+            feature groups.
+        </p>
+        
+        <div id="map" class="smallmap"></div>
+        
+        <div id="docs">
+            <p>
+                This example uses four rules to render features.  Rules are
+                based on a feature attribute and determine which symbolizer
+                is applied when rendering a feature.  The rules in this example
+                change which marker is used by providing an externalGraphic
+                property in the symbolizer.
+            </p>
+                The features are labeled with the same attribute that determines
+                the symbolizer used.  You should be able to confirm that the
+                graphic color corresponds to the range of numbers given below.
+            </p>
+            <ul>
+                <li>0 &lt;= blue &lt; 25
+                <li>25 &lt;= green &lt; 50
+                <li>50 &lt;= gold &lt;= 75
+                <li>75 &lt; red &lt;= 100
+            </ul>
+            <p>
+                See the <a href="style-rules.js" target="_blank">
+                style-rules.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/style-rules.js (from rev 10919, trunk/openlayers/examples/style-rules.js)
===================================================================
--- sandbox/ahocevar/playground/examples/style-rules.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/style-rules.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,99 @@
+var map;
+
+function init() {
+    map = new OpenLayers.Map("map");
+
+    var wms = new OpenLayers.Layer.WMS(
+        "OpenLayers WMS",
+        "http://vmap0.tiles.osgeo.org/wms/vmap0",
+        {layers: "basic"}
+    );
+    
+    /**
+     * Create 50 vector features.  Your features would typically be fetched
+     * from the server.  These are created here to demonstrate a rule based
+     * style.  The features are given an attribute named "foo".  The value
+     * of this attribute is an integer that ranges from 0 to 100.
+     */   
+    var features = new Array(25);
+    for (var i=0; i<features.length; i++) {
+        features[i] = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(
+                (340 * Math.random()) - 170,
+                (160 * Math.random()) - 80
+            ), {
+                foo: 100 * Math.random() | 0
+            }
+        );
+    }
+    
+    /**
+     * Here we create a new style object with rules that determine
+     * which symbolizer will be used to render each feature.
+     */
+    var style = new OpenLayers.Style(
+        // the first argument is a base symbolizer
+        // all other symbolizers in rules will extend this one
+        {
+            graphicWidth: 21,
+            graphicHeight: 25,
+            graphicYOffset: -28, // shift graphic up 28 pixels
+            label: "${foo}" // label will be foo attribute value
+        },
+        // the second argument will include all rules
+        {
+            rules: [
+                new OpenLayers.Rule({
+                    // a rule contains an optional filter
+                    filter: new OpenLayers.Filter.Comparison({
+                        type: OpenLayers.Filter.Comparison.LESS_THAN,
+                        property: "foo", // the "foo" feature attribute
+                        value: 25
+                    }),
+                    // if a feature matches the above filter, use this symbolizer
+                    symbolizer: {
+                        externalGraphic: "../img/marker-blue.png"
+                    }
+                }),
+                new OpenLayers.Rule({
+                    filter: new OpenLayers.Filter.Comparison({
+                        type: OpenLayers.Filter.Comparison.BETWEEN,
+                        property: "foo",
+                        lowerBoundary: 25,
+                        upperBoundary: 50
+                    }),
+                    symbolizer: {
+                        externalGraphic: "../img/marker-green.png"
+                    }
+                }),
+                new OpenLayers.Rule({
+                    filter: new OpenLayers.Filter.Comparison({
+                        type: OpenLayers.Filter.Comparison.BETWEEN,
+                        property: "foo",
+                        lowerBoundary: 50,
+                        upperBoundary: 75
+                    }),
+                    symbolizer: {
+                        externalGraphic: "../img/marker-gold.png"
+                    }
+                }),
+                new OpenLayers.Rule({
+                    // apply this rule if no others apply
+                    elseFilter: true,
+                    symbolizer: {
+                        externalGraphic: "../img/marker.png"
+                    }
+                })
+            ]
+        }
+    );
+    
+    // create the layer styleMap that uses the above style for all render intents
+    var vector = new OpenLayers.Layer.Vector("Points", {
+        styleMap: new OpenLayers.StyleMap(style)
+    });
+    vector.addFeatures(features);
+
+    map.addLayers([wms, vector]);
+    map.setCenter(new OpenLayers.LonLat(0, 0), 1);
+}

Modified: sandbox/ahocevar/playground/examples/style.css
===================================================================
--- sandbox/ahocevar/playground/examples/style.css	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/style.css	2010-11-28 15:48:59 UTC (rev 10920)
@@ -79,4 +79,8 @@
 }
 #tags {
     display: none;
-}
\ No newline at end of file
+}
+
+#docs p {
+    margin-bottom: 0.5em;
+}

Modified: sandbox/ahocevar/playground/examples/stylemap.html
===================================================================
--- sandbox/ahocevar/playground/examples/stylemap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/stylemap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             map = new OpenLayers.Map('map');
             var wms = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             );
             
@@ -38,18 +38,21 @@
                     pointRadius: "${type}", // sized according to type attribute
                     fillColor: "#ffcc66",
                     strokeColor: "#ff9933",
-                    strokeWidth: 2
+                    strokeWidth: 2,
+                    graphicZIndex: 1
                 }),
                 "select": new OpenLayers.Style({
                     fillColor: "#66ccff",
-                    strokeColor: "#3399ff"
+                    strokeColor: "#3399ff",
+                    graphicZIndex: 2
                 })
             });
             
             // Create a vector layer and give it your style map.
-            var points = new OpenLayers.Layer.Vector(
-                'Points', {styleMap: myStyles}
-            );
+            var points = new OpenLayers.Layer.Vector("Points", {
+                styleMap: myStyles,
+                rendererOptions: {zIndexing: true}
+            });
             points.addFeatures(features);
             map.addLayers([wms, points]);
             
@@ -65,7 +68,9 @@
   <body onload="init()">
     <h1 id="title">StyleMap Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        vector, feature, stylemap
+    </div>
 
     <p id="shortdesc">
         Shows how to use a StyleMap to style features with rule based styling.
@@ -88,4 +93,4 @@
         </p>
     </div>
   </body>
-</html>
\ No newline at end of file
+</html>

Modified: sandbox/ahocevar/playground/examples/styles-context.html
===================================================================
--- sandbox/ahocevar/playground/examples/styles-context.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/styles-context.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,7 +10,7 @@
         function init(){
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(wms);
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
             
@@ -81,7 +81,9 @@
   <body onload="init()">
     <h1 id="title">Feature Styles Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        vector, feature, stylemap
+    </div>
 
     <p id="shortdesc">
         To style features with a custom function that evaluates each feature, use
@@ -102,4 +104,4 @@
         on the context object passed to the Style constructor.</p>
     </div>
   </body>
-</html>
\ No newline at end of file
+</html>

Modified: sandbox/ahocevar/playground/examples/styles-rotation.html
===================================================================
--- sandbox/ahocevar/playground/examples/styles-rotation.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/styles-rotation.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,13 +1,8 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>OpenLayers Styles Rotation Example</title>
-    <style type="text/css">
-        #map {
-            width: 800px;
-            height: 475px;
-            border: 1px solid black;
-        }
-    </style>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
     <script src="../lib/OpenLayers.js" type="text/javascript"></script>
     <script type="text/javascript">
         
@@ -18,7 +13,7 @@
             map = new OpenLayers.Map('map');
             var wms = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             );
 
@@ -76,10 +71,19 @@
   </head>
   <body onload="init()">
     <h1 id="title">Rotation Style Example</h1>
-    <p id="shortdesc">To style point features with rotation, use the rotation
-    property of the symbolizer. The center of the rotation is the point of the
-    image specified by graphicXOffset and graphicYOffset.</p>
-    <div id="map"></div>
-    <div id="docs"/>
+    <div id="tags">
+        vector, feature, stylemap, rotation, cleanup
+    </div>    
+    <p id="shortdesc">
+        Use the rotation property of a point symbolizer to rotate
+        point symbolizers.
+    </p>
+    <div id="map" class="smallmap"></div>
+    <div id="docs">
+        To style point features with rotation, use the rotation property of the
+        symbolizer. The center of the rotation is the point of the image
+        specified by graphicXOffset and graphicYOffset. The rotation is
+        specified in degrees clockwise.
+    </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/styles-unique.html
===================================================================
--- sandbox/ahocevar/playground/examples/styles-unique.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/styles-unique.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,7 +10,7 @@
         function init(){
             map = new OpenLayers.Map('map', {maxResolution:'auto'});
             var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(wms);
             map.setCenter(new OpenLayers.LonLat(0, 0), 0);
             
@@ -89,7 +89,9 @@
   <body onload="init()">
     <h1 id="title">Unique Value Styles Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        vector, feature, stylemap, uniquevalue, cleanup
+    </div>
 
     <p id="shortdesc">
         Shows how to create a style based on unique feature attribute values (markers)

Modified: sandbox/ahocevar/playground/examples/sundials-spherical-mercator.html
===================================================================
--- sandbox/ahocevar/playground/examples/sundials-spherical-mercator.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/sundials-spherical-mercator.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -31,15 +31,7 @@
                                                  20037508.34, 20037508.34)
             };
             map = new OpenLayers.Map('map', options);
-            var mapnik = new OpenLayers.Layer.TMS(
-                "OpenStreetMap (Mapnik)",
-                "http://tile.openstreetmap.org/",
-                {
-                    type: 'png', getURL: osm_getTileURL,
-                    displayOutsideMaxExtent: true,
-                    attribution: '<a href="http://www.openstreetmap.org/">OpenStreetMap</a>'
-                }
-            );
+            var mapnik = new OpenLayers.Layer.OSM("OpenStreetMap (Mapnik)");
             var gmap = new OpenLayers.Layer.Google("Google", {sphericalMercator:true});
             var sundials = new OpenLayers.Layer.Vector("KML", {
                 projection: map.displayProjection,
@@ -96,26 +88,14 @@
                 delete feature.popup;
             }
         }
-        function osm_getTileURL(bounds) {
-            var res = this.map.getResolution();
-            var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
-            var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
-            var z = this.map.getZoom();
-            var limit = Math.pow(2, z);
-
-            if (y < 0 || y >= limit) {
-                return OpenLayers.Util.getImagesLocation() + "404.png";
-            } else {
-                x = ((x % limit) + limit) % limit;
-                return this.url + z + "/" + x + "/" + y + "." + this.type;
-            }
-        }
     </script>
   </head>
   <body onload="init()">
       <h1 id="title">OSM + Google Maps + KML Reprojection</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+          osm, kml, spherical, mercator, reprojection, feature, popup, advanced
+      </div>
 
       <p id="shortdesc">
           Demonstrates loading and displaying a KML file on top of OpenStreetMap (OSM) and Google Maps data. Loads data from a KML file of sundials.

Modified: sandbox/ahocevar/playground/examples/sundials.html
===================================================================
--- sandbox/ahocevar/playground/examples/sundials.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/sundials.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -24,7 +24,7 @@
 
             var wms = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'}
             );
 
@@ -91,7 +91,9 @@
   <body onload="init()">
       <h1 id="title">KML Layer Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+          kml, popup, feature
+      </div>
 
       <p id="shortdesc">
           Demonstrates loading and displaying a KML file on top of a basemap.

Modified: sandbox/ahocevar/playground/examples/symbolizers-fill-stroke-graphic.html
===================================================================
--- sandbox/ahocevar/playground/examples/symbolizers-fill-stroke-graphic.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/symbolizers-fill-stroke-graphic.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             map = new OpenLayers.Map('map');
             
             var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             
             // allow testing of specific renderers via "?renderer=Canvas", etc
@@ -25,7 +25,8 @@
                             new OpenLayers.Rule({
                                 symbolizer: {
                                     graphic: false,
-                                    label: "Label for invisible point"
+                                    label: "Label for invisible point",
+                                    labelSelect: true
                                 },
                                 filter: new OpenLayers.Filter.Comparison({
                                     type: "==",
@@ -50,7 +51,9 @@
                                     stroke: true,
                                     fill: false,
                                     label: "Point without fill",
-                                    labelAlign: "rb"
+                                    labelAlign: "rb",
+                                    fontColor: "#ff0000",
+                                    fontOpacity: 0.4
                                 },
                                 filter: new OpenLayers.Filter.Comparison({
                                     type: "==",
@@ -105,18 +108,29 @@
             vectorLayer.drawFeature(multiFeature);
             map.setCenter(new OpenLayers.LonLat(point.x, point.y), 4);
             vectorLayer.addFeatures([pointFeature, polygonFeature, multiFeature]);
+            var select = new OpenLayers.Control.SelectFeature(vectorLayer, {
+                selectStyle: OpenLayers.Util.extend(
+                    {fill: true, stroke: true},
+                    OpenLayers.Feature.Vector.style["select"])
+            });
+            map.addControl(select);
+            select.activate();
         }
     </script>
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Example</h1>
-    <div id="tags"></div>
+    <div id="tags">
+        vector, feature, symbolizer, filter, comparison, labeling
+    </div>
     <p id="shortdesc">
         Demonstrate fill, stroke, and graphic property of symbolizers.
     </p>
     <div id="map" class="smallmap"></div>
     <div id="docs">
     This example shows how to use symbolizers with defaults for stroke, fill, and graphic.
+    This also allows to create labels for a feature without the feature rendered. Click on
+    the label in the middle to see selection of features with labelSelect set to true.
     </div>
   </body>
 </html>

Modified: sandbox/ahocevar/playground/examples/teleportation.html
===================================================================
--- sandbox/ahocevar/playground/examples/teleportation.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/teleportation.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -29,7 +29,7 @@
             });
             map.addControl(new OpenLayers.Control.OverviewMap());
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'} );
             map.addLayer(layer);
             map.zoomTo(2);
@@ -49,7 +49,9 @@
   <body onload="init()">
     <h1 id="title">Map "Teleportation" and Rendering</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        map, rendering
+    </div>
 
     <p id="shortdesc">Call the map's render method to change its container.</p>
 


Property changes on: sandbox/ahocevar/playground/examples/thinlong.jpg
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/examples/tilecache.html
===================================================================
--- sandbox/ahocevar/playground/examples/tilecache.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/tilecache.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,11 +11,11 @@
                 resolutions: [0.087890625, 0.0439453125, 0.02197265625, 0.010986328125]
             });
             layer = new OpenLayers.Layer.TileCache("TileCache Layer",
-                ["http://c0.labs.metacarta.com/wms-c/cache/",
-                 "http://c1.labs.metacarta.com/wms-c/cache/",
-                 "http://c2.labs.metacarta.com/wms-c/cache/",
-                 "http://c3.labs.metacarta.com/wms-c/cache/",
-                 "http://c4.labs.metacarta.com/wms-c/cache/"],
+                ["http://c0.tilecache.osgeo.org/wms-c/cache/",
+                 "http://c1.tilecache.osgeo.org/wms-c/cache/",
+                 "http://c2.tilecache.osgeo.org/wms-c/cache/",
+                 "http://c3.tilecache.osgeo.org/wms-c/cache/",
+                 "http://c4.tilecache.osgeo.org/wms-c/cache/"],
                 "basic",
                 {
                     serverResolutions: [0.703125, 0.3515625, 0.17578125, 0.087890625, 
@@ -44,7 +44,9 @@
   <body onload="init()">
       <h1 id="title">TileCache Example</h1>
 
-      <div id="tags"></div>
+      <div id="tags">
+          tile, cache, tilecache, wmsc, wms-c
+      </div>
 
       <p id="shortdesc">
         Demonstrates a TileCache layer that loads tiles from from a web

Modified: sandbox/ahocevar/playground/examples/tms.html
===================================================================
--- sandbox/ahocevar/playground/examples/tms.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/tms.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
         function init(){
             map = new OpenLayers.Map( 'map', {maxResolution:1.40625/2} );
             layer = new OpenLayers.Layer.TMS( "TMS",
-                    "http://labs.metacarta.com/wms-c/Basic.py/", {layername: 'basic', type:'png'} );
+                    "http://tilecache.osgeo.org/wms-c/Basic.py/", {layername: 'basic', type:'png'} );
             map.addLayer(layer);
             map.addControl(new OpenLayers.Control.LayerSwitcher());
             map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
@@ -34,7 +34,9 @@
   <body onload="init()">
       <h1 id="title">Tiled Map Service Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        tile, cache, tms
+    </div>
 
     <p id="shortdesc">
         Demonstrate the initialization and modification of a Tiled Map Service layer.
@@ -43,9 +45,9 @@
     <div id="map" class="smallmap"></div>
 
     <div id="docs">
-        URL of TMS (Should end in /): <input type="text" id="url" size="60" value="http://labs.metacarta.com/wms-c/Basic.py/" /> layer_name <input type="text" id="layer" value="satellite" /> <select id="type"><option>jpg</option><option>png</option></select> <input type="submit" onclick="addTMS()"/><br />
+        URL of TMS (Should end in /): <input type="text" id="url" size="60" value="http://tilecache.osgeo.org/wms-c/Basic.py/" /> layer_name <input type="text" id="layer" value="basic" /> <select id="type"><option>jpg</option><option>png</option></select> <input type="submit" onclick="addTMS()"/><br />
         <p>
-        Example: http://labs.metacarta.com/wms-c/Basic.py/, satellite, jpg<br />
+        Example: http://tilecache.osgeo.org/wms-c/Basic.py/, basic, jpg<br />
         The first input must be an HTTP URL pointing to a TMS instance. The second
         input must be a layer name available from that instance, and the third must
         be the output format used by that layer. (Any other behavior will result in

Copied: sandbox/ahocevar/playground/examples/transform-feature.html (from rev 10919, trunk/openlayers/examples/transform-feature.html)
===================================================================
--- sandbox/ahocevar/playground/examples/transform-feature.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/transform-feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,106 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers: Transformation Box</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js" type="text/javascript"></script>
+    <script type="text/javascript">
+        var map, control;
+
+        function init(){
+            map = new OpenLayers.Map('map', {allOverlays: true});
+
+            // context for appropriate scale/resize cursors
+            var cursors = ["sw-resize", "s-resize", "se-resize",
+                "e-resize", "ne-resize", "n-resize", "nw-resize", "w-resize"];
+            var context = {
+                getCursor: function(feature){
+                    var i = OpenLayers.Util.indexOf(control.handles, feature);
+                    var cursor = "inherit";
+                    if(i !== -1) {
+                        i = (i + 8 + Math.round(control.rotation / 90) * 2) % 8;
+                        cursor = cursors[i];
+                    }
+                    return cursor;
+                }
+            };
+            
+            // a nice style for the transformation box
+            var style = new OpenLayers.Style({
+                cursor: "${getCursor}",
+                pointRadius: 5,
+                fillColor: "white",
+                fillOpacity: 1,
+                strokeColor: "black"
+            }, {context: context});
+                                    
+            // the layer that we want to transform features on
+            var vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", {
+                styleMap: new OpenLayers.StyleMap({
+                    "transform": style
+                })
+            });
+
+            // create the TransformFeature control, using the renderIntent
+            // from above
+            control = new OpenLayers.Control.TransformFeature(vectorLayer, {
+                renderIntent: "transform"
+            });
+            map.addControl(control);
+
+            // create a polygon feature from a linear ring of points
+            var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+            var pointList = [];
+            for(var p=0; p<6; ++p) {
+                var a = p * (2 * Math.PI) / 7;
+                var r = Math.random(1) + 2;
+                var newPoint = new OpenLayers.Geometry.Point(point.x + (r * Math.cos(a)),
+                                                             point.y + (r * Math.sin(a)));
+                pointList.push(newPoint);
+            }
+            pointList.push(pointList[0]);
+
+            var linearRing = new OpenLayers.Geometry.LinearRing(pointList);
+            var polygonFeature = new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Polygon([linearRing]));
+
+
+            map.addLayer(vectorLayer);
+            map.setCenter(new OpenLayers.LonLat(point.x, point.y), 5);
+            var anotherFeature = polygonFeature.clone();
+            polygonFeature.geometry.move(-3, 0);
+            anotherFeature.geometry.move(3, 0);
+            vectorLayer.addFeatures([polygonFeature, anotherFeature]);
+            
+            // start with the transformation box on polygonFeature
+            control.setFeature(polygonFeature, {rotation: 45, scale: 0.5, ratio: 1.5});
+        }
+    </script>
+  </head>
+  <body onload="init()">
+<h1 id="title">Vector Feature Transformation Box Example</h1>
+
+<div id="tags">
+    vector, feature, transformation, stylemap
+</div>
+<p id="shortdesc">
+    Shows the use of the TransformFeature control.
+</p>
+<div style="text-align: right">
+    <div dir="rtl" id="map" class="smallmap"></div>
+</div>
+<div id="docs">
+    <p>This example shows transformation of vector features with a
+       tranformation box. Grab one of the handles to resize the feature.
+       Holding the SHIFT key will preserve the aspect ratio. Position the
+       mouse right outside one of the corner handles to rotate the feature,
+       and hold the SHIFT key to only rotate in 45° increments.</p>
+       <p>In this example, the transformation box has been set on the left
+       feature, with a rotation preset of 45°. Clicking on the right feature
+       will set it for transformation, starting with an unrotated box.
+       Dragging a feature or the box edges will move it around.</p>
+</div>
+
+  </body>
+</html>
+

Modified: sandbox/ahocevar/playground/examples/transition.html
===================================================================
--- sandbox/ahocevar/playground/examples/transition.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/transition.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,24 +10,24 @@
 
             var single_default_effect = new OpenLayers.Layer.WMS(
                 "WMS untiled default", 
-                "http://labs.metacarta.com/wms/vmap0?",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                 {layers: 'basic'}, 
                 {singleTile: true}
             );
             var single_resize_effect = new OpenLayers.Layer.WMS(
                 "WMS untiled resize", 
-                "http://labs.metacarta.com/wms/vmap0?",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                 {layers: 'basic'}, 
                 {singleTile: true, transitionEffect: 'resize'}
             );
             var tiled_default_effect = new OpenLayers.Layer.WMS(
                 "WMS tiled default ", 
-                "http://labs.metacarta.com/wms/vmap0?",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                 {layers: 'basic'}
             );
             var tiled_resize_effect = new OpenLayers.Layer.WMS(
                 "WMS tiled resize", 
-                "http://labs.metacarta.com/wms/vmap0?",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?",
                 {layers: 'basic'}, 
                 {transitionEffect: 'resize'}
             );
@@ -41,6 +41,9 @@
   </head>
   <body onload="init()">
     <h1 id="title">Transition Example</h1>
+    <div id="tags">
+        transition, resize, tile, singletile
+    </div>    
     <p id="shortdesc">
         Demonstrates the use of transition effects in tiled and untiled layers.
     </p>
@@ -60,4 +63,4 @@
     </div>
   </body>
   </body>
-</html>
\ No newline at end of file
+</html>

Modified: sandbox/ahocevar/playground/examples/urban.html
===================================================================
--- sandbox/ahocevar/playground/examples/urban.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/urban.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -24,7 +24,9 @@
   <body onload="init()">
     <h1 id="title">WorldWind Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        worldwind, cleanup
+    </div>
 
     <p id="shortdesc">
         Demonstrate the use of a NASA WorldWind base layer.

Modified: sandbox/ahocevar/playground/examples/ve-novibrate.html
===================================================================
--- sandbox/ahocevar/playground/examples/ve-novibrate.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/ve-novibrate.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -46,7 +46,9 @@
   <body onload="init()"> 
     <h1 id="title">Virtual Earth Example</h1> 
  
-    <div id="tags"></div> 
+    <div id="tags">
+        panning, virtual earth, panzoom, panmethod, panduration
+    </div> 
  
     <p id="shortdesc"> 
         When using the PanZoom buttons with VirtualEarth, some 'drift' is 

Modified: sandbox/ahocevar/playground/examples/ve.html
===================================================================
--- sandbox/ahocevar/playground/examples/ve.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/ve.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -8,28 +8,24 @@
     <script src="../lib/OpenLayers.js"></script>
     <script type="text/javascript">
 
-        var lon = 5;
-        var lat = 40;
+        var lon = 12;
+        var lat = 41;
         var zoom = 15;
-        var map, velayer, layer;
+        var map, velayer, layer, marker;
 
         function init(){
             map = new OpenLayers.Map( 'map' ,
             {controls:[new OpenLayers.Control.MouseDefaults()]});
 
-            velayer = new OpenLayers.Layer.VirtualEarth( "VE",
-            { minZoomLevel: 4, maxZoomLevel: 6, 'type': VEMapStyle.Aerial});
+            velayer = new OpenLayers.Layer.VirtualEarth( "VE", {
+                // turn off animated zooming
+                animationEnabled: false,
+                minZoomLevel: 4,
+                maxZoomLevel: 6,
+                'type': VEMapStyle.Aerial
+            });
             map.addLayer(velayer);
 
-            var twms = new OpenLayers.Layer.WMS( "World Map",
-                        "http://world.freemap.in/cgi-bin/mapserv?",
-                        { map: '/www/freemap.in/world/map/factbooktrans.map',
-                          transparent:'true',
-                          layers: 'factbook',
-                          'format':'png'},
-                          {'reproject': true});
-            map.addLayer(twms);
-
             markers = new OpenLayers.Layer.Markers("markers");
             map.addLayer(markers);
 
@@ -39,27 +35,33 @@
         }
 
         function add() {
-
-            marker = new OpenLayers.Marker(new OpenLayers.LonLat(2, 41));
-            markers.addMarker(marker);
+            if(!marker) {
+                marker = new OpenLayers.Marker(new OpenLayers.LonLat(15, 47));
+                markers.addMarker(marker);
+            }
         }
 
         function remove() {
-            markers.removeMarker(marker);
+            if(marker) {
+                markers.removeMarker(marker);
+                marker = null;
+            }
         }
     </script>
   </head>
   <body onload="init()">
     <h1 id="title">Virtual Earth Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        virtual earth, marker
+    </div>
 
     <p id="shortdesc">
         Demonstrates the use of a Virtual Earth base layer.
     </p>
 
     <div id="map" class="smallmap"></div>
-    <input type="button" onClick="javascript:add()"value="Add the marker from the map">
+    <input type="button" onClick="javascript:add()"value="Add the marker to the map">
     <input type="button" onClick="javascript:remove()" value="Remove the marker from the map">
     <div id="docs">This example demonstrates the ability to add VirtualEarth and the and remove markers.</div>
   </body>

Modified: sandbox/ahocevar/playground/examples/vector-features-with-text.html
===================================================================
--- sandbox/ahocevar/playground/examples/vector-features-with-text.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/vector-features-with-text.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
             map = new OpenLayers.Map('map');
             
             var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
             
             // allow testing of specific renderers via "?renderer=Canvas", etc
@@ -33,7 +33,9 @@
                     fontSize: "12px",
                     fontFamily: "Courier New, monospace",
                     fontWeight: "bold",
-                    labelAlign: "${align}"
+                    labelAlign: "${align}",
+                    labelXOffset: "${xOffset}",
+                    labelYOffset: "${yOffset}"
                 }}),
                 renderers: renderer
             });
@@ -83,6 +85,22 @@
                     favColor: 'black',
                     align: 'rt'
                 });
+
+            // Create a point feature to show the label offset options
+            var labelOffsetPoint = new OpenLayers.Geometry.Point(-101.04, 35.68);
+            var labelOffsetFeature = new OpenLayers.Feature.Vector(labelOffsetPoint);
+            labelOffsetFeature.attributes = {
+                name: "offset",
+                age: 22,
+                favColor: 'blue',
+                align: "cm",
+                // positive value moves the label to the right
+                xOffset: 50,
+                // negative value moves the label down
+                yOffset: -15
+            };
+
+
             var nullFeature = new OpenLayers.Feature.Vector(null);
             nullFeature.attributes = {
                 name: "toto is some text about the world",
@@ -94,13 +112,15 @@
             map.addLayer(vectorLayer);
             vectorLayer.drawFeature(multiFeature);
             map.setCenter(new OpenLayers.LonLat(point.x, point.y), 3);
-            vectorLayer.addFeatures([pointFeature, polygonFeature, multiFeature, nullFeature ]);
+            vectorLayer.addFeatures([pointFeature, polygonFeature, multiFeature, labelOffsetFeature, nullFeature ]);
         }
     </script>
   </head>
   <body onload="init()">
     <h1 id="title">OpenLayers Labeled features example</h1>
-    <div id="tags"></div>
+    <div id="tags">
+        vector, feature, labeling, symbolizer
+    </div>
     <p id="shortdesc">
         Label vector features with a text symbolizer.
     </p>

Modified: sandbox/ahocevar/playground/examples/vector-features.html
===================================================================
--- sandbox/ahocevar/playground/examples/vector-features.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/vector-features.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>OpenLayers: Vector Features</title>
@@ -10,7 +11,7 @@
         function init(){
             map = new OpenLayers.Map('map');
             var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
 
             /*
@@ -59,11 +60,11 @@
             // of the image will be ignored
             style_mark.graphicWidth = 24;
             style_mark.graphicHeight = 20;
-            style_mark.graphicXOffset = -(style_mark.graphicWidth/2);  // this is the default value
+            style_mark.graphicXOffset = 10; // default is -(style_mark.graphicWidth/2);
             style_mark.graphicYOffset = -style_mark.graphicHeight;
             style_mark.externalGraphic = "../img/marker.png";
             // graphicTitle only works in Firefox and Internet Explorer
-			style_mark.graphicTitle = "this is a test tooltip";
+            style_mark.graphicTitle = "this is a test tooltip";
 
             var vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", {style: layer_style});
 
@@ -112,13 +113,12 @@
 <h1 id="title">Drawing Simple Vector Features Example</h1>
 
 <div id="tags">
+    vector, feature
 </div>
 <p id="shortdesc">
     Shows the use of the shows drawing simple vector features, in different styles.
 </p>
-<div style="text-align: right">
-    <div dir="rtl" id="map" class="smallmap"></div>
-</div>
+<div id="map" class="smallmap"></div>
 <div id="docs">
     <p>This example shows drawing simple vector features -- point, line, polygon
        in different styles, created 'manually', by constructing the entire style

Modified: sandbox/ahocevar/playground/examples/vector-formats.html
===================================================================
--- sandbox/ahocevar/playground/examples/vector-formats.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/vector-formats.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -69,6 +69,8 @@
                 OpenLayers.Util.extend({}, gmlOptions),
                 out_options
             );
+            var kmlOptionsIn = OpenLayers.Util.extend(
+                {extractStyles: true}, in_options);
             formats = {
               'in': {
                 wkt: new OpenLayers.Format.WKT(in_options),
@@ -76,7 +78,8 @@
                 georss: new OpenLayers.Format.GeoRSS(in_options),
                 gml2: new OpenLayers.Format.GML.v2(gmlOptionsIn),
                 gml3: new OpenLayers.Format.GML.v3(gmlOptionsIn),
-                kml: new OpenLayers.Format.KML(in_options)
+                kml: new OpenLayers.Format.KML(kmlOptionsIn),
+                atom: new OpenLayers.Format.Atom(in_options)
               }, 
               'out': {
                 wkt: new OpenLayers.Format.WKT(out_options),
@@ -84,14 +87,15 @@
                 georss: new OpenLayers.Format.GeoRSS(out_options),
                 gml2: new OpenLayers.Format.GML.v2(gmlOptionsOut),
                 gml3: new OpenLayers.Format.GML.v3(gmlOptionsOut),
-                kml: new OpenLayers.Format.KML(out_options)
+                kml: new OpenLayers.Format.KML(out_options),
+                atom: new OpenLayers.Format.Atom(out_options)
               } 
             };
         }
         function init(){
             map = new OpenLayers.Map('map');
             var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'});
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'});
 
             vectors = new OpenLayers.Layer.Vector("Vector Layer");
 
@@ -142,7 +146,7 @@
                 vectors.addFeatures(features);
                 map.zoomToExtent(bounds);
                 var plural = (features.length > 1) ? 's' : '';
-                element.value = features.length + ' feature' + plural + ' added'
+                element.value = features.length + ' feature' + plural + ' added';
             } else {
                 element.value = 'Bad input ' + type;
             }
@@ -168,6 +172,7 @@
         <h1 id="title">Vector Formats Example</h1>
 
         <div id="tags">
+            vector, geojson, atom, kml, georss, gml, wkt, advanced, spherical, mercator
         </div>
         <p id="shortdesc">
             Shows the wide variety of vector formats that open layers supports.
@@ -181,6 +186,7 @@
             <label for="formatType">Format</label>
             <select name="formatType" id="formatType">
                 <option value="geojson" selected="selected">GeoJSON</option>
+                <option value="atom">Atom</option>
                 <option value="kml">KML</option>
                 <option value="georss">GeoRSS</option>
                 <option value="gml2">GML (v2)</option>

Copied: sandbox/ahocevar/playground/examples/web-mercator.html (from rev 10919, trunk/openlayers/examples/web-mercator.html)
===================================================================
--- sandbox/ahocevar/playground/examples/web-mercator.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/web-mercator.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title>OpenLayers: Web Mercator</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
+
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="web-mercator.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">OpenLayers Spherical Mercator Example</h1>
+
+        <div id="tags">
+            sperical, mercator, epsg, projection
+        </div>
+        <p id="shortdesc">
+            Shows the use of layers in spherical or web mercator using different
+            EPSG codes to indicate the same projection.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                A number of mapping services support the spherical or web
+                mercator but use different EPSG codes to identify it. ArcGIS
+                server version 9.3 uses EPSG:102113 to represent the same SRS
+                that OpenLayers typically refers to by EPSG:900913.
+            </p><p>
+                To configure a map with a WMS layer overlaid on a Google layer
+                where the WMS uses EPSG:102113 to refer to the web mercator 
+                projection, the Google layer must be constructed with this 
+                projection code in its options (it is not sufficient to 
+                construct the map with this projection).  
+            <p>
+                If your application needs to transform coordinates to and from
+                EPSG:102113, you must add custom transforms as well.
+            </p><p>
+                See the <a href="web-mercator.js" target="_blank">web-mercator.js</a>
+                source for details.
+            </p>
+        </div>
+    </body>
+</html>
+
+
+

Copied: sandbox/ahocevar/playground/examples/web-mercator.js (from rev 10919, trunk/openlayers/examples/web-mercator.js)
===================================================================
--- sandbox/ahocevar/playground/examples/web-mercator.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/web-mercator.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,45 @@
+// make map available for easy debugging
+var map;
+
+// if your application transforms coordinates to and from EPSG:102113 then
+// you must uncomment the lines below
+
+// OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:102113",
+//     OpenLayers.Layer.SphericalMercator.projectForward);
+// OpenLayers.Projection.addTransform("EPSG:102113", "EPSG:4326",
+//     OpenLayers.Layer.SphericalMercator.projectInverse);
+
+function init() {
+
+    var options = {
+        projection: new OpenLayers.Projection("EPSG:102113"),
+        units: "m",
+        numZoomLevels: 18,
+        maxResolution: 156543.0339,
+        maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
+                                         20037508, 20037508.34)
+    };
+    map = new OpenLayers.Map('map', options);
+
+    // create Google layer with EPSG:102113 code
+    var gsat = new OpenLayers.Layer.Google("Google Imagery", {
+        type: G_SATELLITE_MAP, 
+        sphericalMercator: true,
+        projection: "EPSG:102113"
+    });
+
+    // create WMS layer
+    var wms = new OpenLayers.Layer.WMS(
+        "Highways",
+        "http://sampleserver1.arcgisonline.com/arcgis/services/Specialty/ESRI_StateCityHighway_USA/MapServer/WMSServer",
+        {layers: "2", format: "image/gif", transparent: "true"},
+        {
+            isBaseLayer: false,
+            wrapDateLine: true
+        }
+    );
+
+    map.addLayers([gsat, wms]);
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.setCenter(new OpenLayers.LonLat(-10723197, 4500612), 3);
+}

Copied: sandbox/ahocevar/playground/examples/wfs-filter.html (from rev 10919, trunk/openlayers/examples/wfs-filter.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-filter.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wfs-filter.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers WFS Protocol with Filter</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
+        <link rel="stylesheet" href="../theme/default/google.css" type="text/css">
+        <link rel="stylesheet" href="style.css" type="text/css">
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="wfs-filter.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">WFS Protocol and Filter</h1>
+        <div id="tags">
+            filter, wfs, comparison
+        </div>
+        <p id="shortdesc">
+            Demonstrates the use of a filter in making GetFeature requests using the WFS protocol.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                If a vector layer has a filter and the protocol supports server-side filtering,
+                the filter will be serialized in requests for features.  The WFS protocol can be
+                used with a vector layer to serialize a filter using OGC Filter Encoding.  This
+                example requests all features that are <code>TYPE</code> "highway" or "road".
+            </p><p>
+                See the <a href="wfs-filter.js" target="_blank">wfs-filter source</a> 
+                for details on how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/wfs-filter.js (from rev 10919, trunk/openlayers/examples/wfs-filter.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-filter.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wfs-filter.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,48 @@
+var map;
+
+// use proxy if requesting features cross-domain
+OpenLayers.ProxyHost= "proxy.cgi?url=";
+
+function init() {
+
+    map = new OpenLayers.Map({
+        div: "map",
+        layers: [
+            new OpenLayers.Layer.WMS(
+                "Natural Earth", 
+                "http://demo.opengeo.org/geoserver/wms",
+                {layers: "topp:naturalearth"}
+            ),
+            new OpenLayers.Layer.Vector("WFS", {
+                strategies: [new OpenLayers.Strategy.BBOX()],
+                protocol: new OpenLayers.Protocol.WFS({
+                    url:  "http://demo.opengeo.org/geoserver/wfs",
+                    featureType: "tasmania_roads",
+                    featureNS: "http://www.openplans.org/topp"
+                }),
+                styleMap: new OpenLayers.StyleMap({
+                    strokeWidth: 3,
+                    strokeColor: "#333333"
+                }),
+                filter: new OpenLayers.Filter.Logical({
+                    type: OpenLayers.Filter.Logical.OR,
+                    filters: [
+                        new OpenLayers.Filter.Comparison({
+                            type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                            property: "TYPE",
+                            value: "highway"
+                        }),
+                        new OpenLayers.Filter.Comparison({
+                            type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                            property: "TYPE",
+                            value: "road"
+                        })
+                    ]
+                })
+            })
+        ],
+        center: new OpenLayers.LonLat(146.7, -41.8),
+        zoom: 6
+    });
+
+}

Modified: sandbox/ahocevar/playground/examples/wfs-protocol-transactions.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-protocol-transactions.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs-protocol-transactions.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -58,140 +58,34 @@
             background-position: 0px 1px;
         }
     </style>
-    <script type="text/javascript">
-        var map, wfs;
-        
-        var DeleteFeature = OpenLayers.Class(OpenLayers.Control, {
-            initialize: function(layer, options) {
-                OpenLayers.Control.prototype.initialize.apply(this, [options]);
-                this.layer = layer;
-                this.handler = new OpenLayers.Handler.Feature(
-                    this, layer, {click: this.clickFeature}
-                );
-            },
-            clickFeature: function(feature) {
-                // if feature doesn't have a fid, destroy it
-                if(feature.fid == undefined) {
-                    this.layer.destroyFeatures([feature]);
-                } else {
-                    feature.state = OpenLayers.State.DELETE;
-                    this.layer.events.triggerEvent("afterfeaturemodified", 
-                                                   {feature: feature});
-                    feature.renderIntent = "select";
-                    this.layer.drawFeature(feature);
-                }
-            },
-            setMap: function(map) {
-                this.handler.setMap(map);
-                OpenLayers.Control.prototype.setMap.apply(this, arguments);
-            },
-            CLASS_NAME: "OpenLayers.Control.DeleteFeature"
-        });
-
-        function init() {
-            OpenLayers.ProxyHost= "proxy.cgi?url=";
-            map = new OpenLayers.Map('map', {
-                projection: new OpenLayers.Projection("EPSG:900913"),
-                displayProjection: new OpenLayers.Projection("EPSG:4326"),
-                units: "m",
-                maxResolution: 156543.0339,
-                maxExtent: new OpenLayers.Bounds(
-                    -11593508, 5509847, -11505759, 5557774
-                ),
-                controls: [
-                    new OpenLayers.Control.PanZoom()
-                ]
-            });
-            var gphy = new OpenLayers.Layer.Google(
-                "Google Physical",
-                {type: G_PHYSICAL_MAP, sphericalMercator: true}
-            );
-
-            var saveStrategy = new OpenLayers.Strategy.Save();
-
-            wfs = new OpenLayers.Layer.Vector("Editable Features", {
-                strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
-                projection: new OpenLayers.Projection("EPSG:4326"),
-                protocol: new OpenLayers.Protocol.WFS({
-                    version: "1.1.0",
-                    srsName: "EPSG:4326",
-                    url: "http://demo.opengeo.org/geoserver/wfs",
-                    featureNS :  "http://opengeo.org",
-                    featureType: "restricted",
-                    geometryName: "the_geom",
-                    schema: "http://demo.opengeo.org/geoserver/wfs/DescribeFeatureType?version=1.1.0&typename=og:restricted"
-                })
-            }); 
-           
-            map.addLayers([gphy, wfs]);
-
-            var panel = new OpenLayers.Control.Panel(
-                {'displayClass': 'customEditingToolbar'}
-            );
-            
-            var navigate = new OpenLayers.Control.Navigation({
-                title: "Pan Map",
-            });
-            
-            var draw = new OpenLayers.Control.DrawFeature(
-                wfs, OpenLayers.Handler.Polygon,
-                {
-                    title: "Draw Feature",
-                    displayClass: "olControlDrawFeaturePolygon",
-                    handlerOptions: {multi: true}
-                }
-            );
-            
-            var edit = new OpenLayers.Control.ModifyFeature(wfs, {
-                title: "Modify Feature",
-                displayClass: "olControlModifyFeature",
-            });
-
-            var del = new DeleteFeature(wfs, {title: "Delete Feature"});
-           
-            var save = new OpenLayers.Control.Button({
-                title: "Save Changes",
-                trigger: function() {
-                    if(edit.feature) {
-                        edit.selectControl.unselectAll();
-                    }
-                    saveStrategy.save();
-                },
-                displayClass: "olControlSaveFeatures"
-            });
-
-            panel.addControls([navigate, save, del, edit, draw]);
-            panel.defaultControl = navigate;
-            map.addControl(panel);
-            map.zoomToMaxExtent();
-        }
-        
-    </script>
+    <script src="wfs-protocol-transactions.js"></script>
     </head>
     <body onload="init()">
-    
-    <h1 id="title">WFS Transaction Example</h1>
-    
-    <div id="tags">
-    </div>
-    <p id="shortdesc">
-        Shows the use of the WFS Transactions (WFS-T).
-    </p>
-    
-    <div id="map" class="smallmap"></div>
-
-    <div id="docs">
-        <p>The WFS protocol allows for creation of new features and reading,
-        updating, or deleting of existing features.</p>
-        <p>Use the tools to create, modify, and delete (in order from left
-        to right) features.  Use the save tool (picture of a disk) to
-        save your changes.  Use the navigation tool (hand) to stop editing
-        and use the mouse for map navigation.</p>
-    </div>
-
-
-
-</body>
+        <h1 id="title">WFS Transaction Example</h1>
+        <div id="tags">
+            wfs, wfst, wfs-t, advanced
+        </div>
+        <p id="shortdesc">
+            Shows the use of the WFS Transactions (WFS-T).
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                The WFS protocol allows for creation of new features and
+                reading, updating, or deleting of existing features.
+            </p>
+            <p>
+                Use the tools to create, modify, and delete (in order from left
+                to right) features. Use the save tool (picture of a disk) to
+                save your changes. Use the navigation tool (hand) to stop
+                editing and use the mouse for map navigation.
+            </p>
+            <p>
+                See the <a href="wfs-protocol-transactions.js" target="_blank">
+                wfs-protocol-transactions.js source</a> to see how this is done.
+            </p>        
+        </div>
+    </body>
 </html>
 
 

Copied: sandbox/ahocevar/playground/examples/wfs-protocol-transactions.js (from rev 10919, trunk/openlayers/examples/wfs-protocol-transactions.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-protocol-transactions.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wfs-protocol-transactions.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,107 @@
+var map, wfs;
+OpenLayers.ProxyHost = "proxy.cgi?url=";
+
+var DeleteFeature = OpenLayers.Class(OpenLayers.Control, {
+    initialize: function(layer, options) {
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        this.layer = layer;
+        this.handler = new OpenLayers.Handler.Feature(
+            this, layer, {click: this.clickFeature}
+        );
+    },
+    clickFeature: function(feature) {
+        // if feature doesn't have a fid, destroy it
+        if(feature.fid == undefined) {
+            this.layer.destroyFeatures([feature]);
+        } else {
+            feature.state = OpenLayers.State.DELETE;
+            this.layer.events.triggerEvent("afterfeaturemodified", 
+                                           {feature: feature});
+            feature.renderIntent = "select";
+            this.layer.drawFeature(feature);
+        }
+    },
+    setMap: function(map) {
+        this.handler.setMap(map);
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+    CLASS_NAME: "OpenLayers.Control.DeleteFeature"
+});
+
+function init() {
+    map = new OpenLayers.Map('map', {
+        projection: new OpenLayers.Projection("EPSG:900913"),
+        displayProjection: new OpenLayers.Projection("EPSG:4326"),
+        units: "m",
+        maxResolution: 156543.0339,
+        maxExtent: new OpenLayers.Bounds(
+            -11593508, 5509847, -11505759, 5557774
+        ),
+        controls: [
+            new OpenLayers.Control.PanZoom()
+        ]
+    });
+    var gphy = new OpenLayers.Layer.Google(
+        "Google Physical",
+        {type: G_PHYSICAL_MAP, sphericalMercator: true}
+    );
+
+    var saveStrategy = new OpenLayers.Strategy.Save();
+
+    wfs = new OpenLayers.Layer.Vector("Editable Features", {
+        strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
+        projection: new OpenLayers.Projection("EPSG:4326"),
+        protocol: new OpenLayers.Protocol.WFS({
+            version: "1.1.0",
+            srsName: "EPSG:4326",
+            url: "http://demo.opengeo.org/geoserver/wfs",
+            featureNS :  "http://opengeo.org",
+            featureType: "restricted",
+            geometryName: "the_geom",
+            schema: "http://demo.opengeo.org/geoserver/wfs/DescribeFeatureType?version=1.1.0&typename=og:restricted"
+        })
+    }); 
+   
+    map.addLayers([gphy, wfs]);
+
+    var panel = new OpenLayers.Control.Panel(
+        {'displayClass': 'customEditingToolbar'}
+    );
+    
+    var navigate = new OpenLayers.Control.Navigation({
+        title: "Pan Map"
+    });
+    
+    var draw = new OpenLayers.Control.DrawFeature(
+        wfs, OpenLayers.Handler.Polygon,
+        {
+            title: "Draw Feature",
+            displayClass: "olControlDrawFeaturePolygon",
+            multi: true
+        }
+    );
+    
+    var edit = new OpenLayers.Control.ModifyFeature(wfs, {
+        title: "Modify Feature",
+        displayClass: "olControlModifyFeature"
+    });
+
+    var del = new DeleteFeature(wfs, {title: "Delete Feature"});
+   
+    var save = new OpenLayers.Control.Button({
+        title: "Save Changes",
+        trigger: function() {
+            if(edit.feature) {
+                edit.selectControl.unselectAll();
+            }
+            saveStrategy.save();
+        },
+        displayClass: "olControlSaveFeatures"
+    });
+
+    panel.addControls([navigate, save, del, edit, draw]);
+    panel.defaultControl = navigate;
+    map.addControl(panel);
+    map.zoomToMaxExtent();
+}
+

Modified: sandbox/ahocevar/playground/examples/wfs-protocol.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-protocol.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs-protocol.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,14 +12,14 @@
                 OpenLayers.ProxyHost= "proxy.cgi?url=";
                 map = new OpenLayers.Map('map');
                 var wms = new OpenLayers.Layer.WMS(
-                    "OpenLayers WMS", "http://labs.metacarta.com/wms/vmap0",
+                    "OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0",
                     {layers: 'basic'}
                 );
 
                 var layer = new OpenLayers.Layer.Vector("WFS", {
                     strategies: [new OpenLayers.Strategy.BBOX()],
                     protocol: new OpenLayers.Protocol.WFS({
-                        url:  "http://publicus.opengeo.org/geoserver/wfs",
+                        url:  "http://demo.opengeo.org/geoserver/wfs",
                         featureType: "tasmania_roads",
                         featureNS: "http://www.openplans.org/topp"
                     })
@@ -32,6 +32,9 @@
     </head>
     <body onload="init()">
         <h1 id="title">Vector Behavior Example</h1>
+        <div id="tags">
+            wfs, vector
+        </div>
         <p id="shortdesc">
             Uses a BBOX strategy, WFS protocol, and GML format.
         </p>

Modified: sandbox/ahocevar/playground/examples/wfs-reprojection.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-reprojection.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs-reprojection.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,114 +1,38 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>WFS Reprojection + Canvas Renderer Example</title>
-    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
-    <link rel="stylesheet" href="style.css" type="text/css" />
-    <script src="../lib/OpenLayers.js"></script>
-    <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
-    <script type="text/javascript">
-
-        var map, layer, styleMap;
-        OpenLayers.ProxyHost = "/proxy/?url=";
-        function init(){
-
-            map = new OpenLayers.Map('map', {
-                projection: new OpenLayers.Projection("EPSG:900913"),
-                displayProjection: new OpenLayers.Projection("EPSG:4326"),
-                units: "m",
-                maxResolution: 156543.0339,
-                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
-                                                 20037508.34, 20037508.34)
-            });
-
-            var g = new OpenLayers.Layer.Google("G", {sphericalMercator: true});
-            map.addLayers([g]);
-
-            // prepare to style the data
-            styleMap = new OpenLayers.StyleMap({
-                strokeColor: "black",
-                strokeWidth: 2,
-                strokeOpacity: 0.5,
-                fillOpacity: 0.2
-            });
-            // create a color table for state FIPS code
-            var colors = ["red", "orange", "yellow", "green", "blue", "purple"];
-            var code, fips = {};
-            for(var i=1; i<=66; ++i) {
-                code = "0" + i;
-                code = code.substring(code.length - 2);
-                fips[code] = {fillColor: colors[i % colors.length]};
-            }
-            // add unique value rules with your color lookup
-            styleMap.addUniqueValueRules("default", "STATE_FIPS", fips);
-
-            // create a wfs layer with a projection different than the map
-            // (only if your wfs doens't support your map projection)
-            var wfs = layer = new OpenLayers.Layer.WFS(
-                "States (SVG)",
-                "http://sigma.openplans.org/geoserver/ows",
-                {typename: 'topp:states'},
-                {
-                    typename: 'states',
-                    featureNS: 'http://www.openplans.org/topp',
-                    projection: new OpenLayers.Projection("EPSG:4326"),
-                    extractAttributes: true,
-                    ratio: 1.2,
-                    styleMap: styleMap
-                }
-            );
-            map.addLayer(wfs);
-            
-            var wfs = layer = new OpenLayers.Layer.WFS(
-                "States (Canvas)",
-                "http://sigma.openplans.org/geoserver/ows",
-                {typename: 'topp:states'},
-                {
-                    typename: 'states',
-                    featureNS: 'http://www.openplans.org/topp',
-                    projection: new OpenLayers.Projection("EPSG:4326"),
-                    extractAttributes: true,
-                    ratio: 1.2,
-                    styleMap: styleMap,
-                    renderers: ['Canvas', 'SVG', 'VML'] 
-                }
-            );
-            map.addLayer(wfs);
-            map.addControl(new OpenLayers.Control.LayerSwitcher());
-
-            // if you want to use Geographic coords, transform to ESPG:900913
-            var ddBounds = new OpenLayers.Bounds(
-                -73.839111,40.287907,-68.214111,44.441624
-            );
-            map.zoomToExtent(
-                ddBounds.transform(map.displayProjection, map.getProjectionObject())
-            );
-        }
-    </script>
-  </head>
-  <body onload="init()">
-
-  <h1 id="title">WFS Reprojection + Canvas Renderer Example</h1>
-
-  <div id="tags">
-  </div>
-  <p id="shortdesc">
-        Shows the use of the WFS layer reprojection support 
-  </p>
-
+    <head>
+        <title>WFS Reprojection Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ"></script>
+        <script src="wfs-reprojection.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">WFS Reprojection Example</h1>
+        <div id="tags">
+            reprojection, styling, stylemap, wfs, vector, advanced
+        </div>
+        <p id="shortdesc">
+            Shows the use of the client side reprojection support. 
+        </p>
         <div id="map" class="smallmap"></div>
-
-  <div id="docs">
-    <p>This example shows automatic WFS reprojection, displaying an 'unprojected'
-    WFS layer projected on the client side over Google Maps. The key configuration
-    here is the 'projection' option on the WFS layer.</p>
-    <p>Also shown is styleMap for the layer with unique value rules.  Colors
-    are assigned based on the STATE_FIPS attribute.</p>
-    <p>Additionally, this map demonstrates the Canvas/SVG renderers in browsers
-       which support both. See the two different layers in the
-       LayerSwitcher.</p>
-  </div>
-
-
-
-  </body>
+        <div id="docs">
+            <p> 
+                This example shows client side reprojection. In the case where
+                the projection of a vector layer differs from the projection of
+                the map, features are requested in the layer projection and
+                transformed during parsing. It is assumed that the layer
+                projection is "native" projection of the data (the coordinate
+                reference system of the data on the server).
+            </p>
+            <p>
+                Also shown is styleMap for the layer with unique value rules.
+                Colors are assigned based on the STATE_FIPS attribute.
+            </p>
+            <p>
+                See the <a href="wfs-reprojection.js" target="_blank">
+                wfs-reprojection.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
 </html>

Copied: sandbox/ahocevar/playground/examples/wfs-reprojection.js (from rev 10919, trunk/openlayers/examples/wfs-reprojection.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-reprojection.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wfs-reprojection.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,65 @@
+var map, layer, styleMap;
+OpenLayers.ProxyHost = "proxy.cgi?url=";
+
+function init() {
+
+    var geographic = new OpenLayers.Projection("EPSG:4326");
+    var mercator = new OpenLayers.Projection("EPSG:900913");
+
+    map = new OpenLayers.Map('map', {
+        projection: mercator,
+        units: "m",
+        maxResolution: 156543.0339,
+        maxExtent: new OpenLayers.Bounds(
+            -20037508, -20037508, 20037508, 20037508
+        )
+    });
+
+    var g = new OpenLayers.Layer.Google("Google Layer", {
+        sphericalMercator: true
+    });
+    map.addLayers([g]);
+
+    // prepare to style the data
+    styleMap = new OpenLayers.StyleMap({
+        strokeColor: "black",
+        strokeWidth: 2,
+        strokeOpacity: 0.5,
+        fillOpacity: 0.2
+    });
+    // create a color table for state FIPS code
+    var colors = ["red", "orange", "yellow", "green", "blue", "purple"];
+    var code, fips = {};
+    for(var i=1; i<=66; ++i) {
+        code = "0" + i;
+        code = code.substring(code.length - 2);
+        fips[code] = {fillColor: colors[i % colors.length]};
+    }
+    // add unique value rules with your color lookup
+    styleMap.addUniqueValueRules("default", "STATE_FIPS", fips);
+
+    // This server supports server-side reprojection, but we're using WFS 1.0 
+    // here (which doesn't support reprojection) to illustrate client-side 
+    // reprojection.
+    var wfs = new OpenLayers.Layer.Vector("States", {
+        strategies: [new OpenLayers.Strategy.BBOX()],
+        protocol: new OpenLayers.Protocol.WFS({
+            version: "1.0.0",
+            srsName: "EPSG:4326", // this is the default
+            url:  "http://demo.opengeo.org/geoserver/wfs",
+            featureType: "states",
+            featureNS: "http://www.openplans.org/topp"
+        }),
+        projection: geographic, // specified because it is different than the map 
+        styleMap: styleMap
+    });
+    map.addLayer(wfs);
+    
+    // if you want to use Geographic coords, transform to ESPG:900913
+    var ddBounds = new OpenLayers.Bounds(
+        -73.839111,40.287907,-68.214111,44.441624
+    );
+    map.zoomToExtent(
+        ddBounds.transform(geographic, mercator)
+    );
+}

Modified: sandbox/ahocevar/playground/examples/wfs-snap-split.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-snap-split.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs-snap-split.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -266,6 +266,7 @@
     <h1 id="title">Snap/Split and Persist via WFS</h1>
     
     <div id="tags">
+        snapping, splitting, wfs, wfst, wfs-t, advanced
     </div>
     <p id="shortdesc">
         Shows snapping, splitting, and use of the WFS Transactions (WFS-T).

Modified: sandbox/ahocevar/playground/examples/wfs-states.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-states.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs-states.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,45 +1,29 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
-    <link rel="stylesheet" href="style.css" type="text/css" />
-    <title>WFS: United States (GeoServer)</title>
-    <script src="../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map, layer;
-
-        function init(){
-            OpenLayers.ProxyHost="proxy.cgi?url=";
-            map = new OpenLayers.Map('map', {controls: [ new OpenLayers.Control.PanZoom(), new OpenLayers.Control.Permalink(), new OpenLayers.Control.MouseDefaults() ]} );
-            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms-c/Basic.py",
-                    {layers: 'basic'} );
-            map.addLayer(layer);
-
-            layer = new OpenLayers.Layer.WFS( "States WFS",
-                    "http://sigma.openplans.org/geoserver/ows",
-                    { typename: 'topp:states' } );
-            map.addLayer(layer);
-
-            map.zoomToExtent(new OpenLayers.Bounds(-140.444336,25.115234,-44.438477,50.580078));
-        }
-    </script>
-  </head>
-  <body onload="init()">
-<h1 id="title">WFS United States (GeoServer) Example</h1>
-
-<div id="tags">
-</div>
-
-<p id="shortdesc">
-    Shows the use of the WFS United States (GeoServer) 
-</p>
-
-<div id="map" class="smallmap"></div>
-
-<div id="docs"></div>
-  </body>
+<html>
+    <head>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <title>WFS: United States (GeoServer)</title>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="wfs-states.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">WFS United States (GeoServer) Example</h1>
+        <div id="tags">
+            wfs, vector
+        </div>
+        <p id="shortdesc">
+            Shows the use of the WFS United States (GeoServer). 
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="docs">
+            <p>
+                This example shows the basic use of a vector layer with the
+                WFS protocol.
+            </p>
+            <p>
+                See the <a href="wfs-states.js" target="_blank">wfs-states.js
+                source</a> to see how this is done.
+            </p> 
+        </div>
+    </body>
 </html>
-
-
-
-</div>

Copied: sandbox/ahocevar/playground/examples/wfs-states.js (from rev 10919, trunk/openlayers/examples/wfs-states.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wfs-states.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wfs-states.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,24 @@
+var map;
+OpenLayers.ProxyHost = "proxy.cgi?url=";
+
+function init() {
+    map = new OpenLayers.Map("map");
+
+    var base = new OpenLayers.Layer.WMS("OpenLayers WMS",
+        "http://tilecache.osgeo.org/wms-c/Basic.py",
+        {layers: "basic"} 
+    );
+    map.addLayer(base);
+
+    var wfs = new OpenLayers.Layer.Vector("States", {
+        strategies: [new OpenLayers.Strategy.BBOX()],
+        protocol: new OpenLayers.Protocol.WFS({
+            url: "http://demo.opengeo.org/geoserver/wfs",
+            featureType: "states",
+            featureNS: "http://www.openplans.org/topp"
+        })
+    });
+    map.addLayer(wfs);
+
+    map.zoomToExtent(new OpenLayers.Bounds(-140.4, 25.1, -44.4, 50.5));
+}

Deleted: sandbox/ahocevar/playground/examples/wfs.html
===================================================================
--- sandbox/ahocevar/playground/examples/wfs.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wfs.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,34 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
-    <link rel="stylesheet" href="style.css" type="text/css" />
-    <script src="../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map, layer;
-
-        function init(){
-            OpenLayers.ProxyHost="/proxy/?url=";
-            map = new OpenLayers.Map('map');
-            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
-            map.addLayer(layer);
-
-            layer = new OpenLayers.Layer.WFS( "Owl Survey",
-                "http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp?",
-                {typename: "OWLS", maxfeatures: 10},
-                { featureClass: OpenLayers.Feature.WFS});
-            map.addLayer(layer);
-            map.addControl(new OpenLayers.Control.LayerSwitcher());
-            map.setCenter(new OpenLayers.LonLat(-100, 60), 3);
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">WFS Points</h1>
-    <p id='shortdesc'>
-      Using a Layer.WFS with a featureClass, one can take in XML data
-      from a WFS class and display it any way you like.
-    </p>  
-    <div id="map" class="smallmap"></div>
-  </body>
-</html>


Property changes on: sandbox/ahocevar/playground/examples/widelong.jpg
___________________________________________________________________
Deleted: svn:executable
   - *


Property changes on: sandbox/ahocevar/playground/examples/wideshort.jpg
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/examples/wmc.html
===================================================================
--- sandbox/ahocevar/playground/examples/wmc.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wmc.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -7,14 +7,18 @@
             width: 90%;
             height: 300px;
         }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
     </style>
     <script src="../lib/Firebug/firebug.js"></script>
     <script src="../lib/OpenLayers.js"></script>
     <script type="text/javascript">
 
-        // no pink please
+        // increase reload attempts 
         OpenLayers.IMAGE_RELOAD_ATTEMPTS = 2;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
         
         var format = new OpenLayers.Format.WMC({'layerOptions': {buffer: 0}});
         var doc, context, map;
@@ -39,7 +43,7 @@
 
             var vmap = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'},
                 {
                     maxExtent: new OpenLayers.Bounds(-130, 14, -60, 55),
@@ -101,7 +105,9 @@
             } else {
                 map.destroy();
                 try {
-                    map = format.read(text, {map: "map"});
+                    var jsonFormat = new OpenLayers.Format.JSON();
+                    var mapOptions = jsonFormat.read(OpenLayers.Util.getElement('mapOptions').value);
+                    map = format.read(text, {map: mapOptions});
                     map.addControl(new OpenLayers.Control.LayerSwitcher());
                 } catch(err) {
                     document.getElementById("wmc").value = err;
@@ -124,14 +130,16 @@
     <h1 id="title">WMC Example</h1>
 
     <div id="tags">
+        wmc, parser, advanced, cleanup
     </div>
     <p id="shortdesc">
            Shows parsing of Web Map Context documents.
     </p>
     <div id="map" class="smallmap"></div>
-        <button onclick="writeWMC();">write</button>
-        <button onclick="readWMC();">read as new map</button>
-        <button onclick="readWMC(true);">read and merge</button>
+        <button onclick="writeWMC();">write</button><br />
+        <button onclick="readWMC();">read as new map</button> with the following extra map options : <input type="text" id="mapOptions" value='{"div": "map", "allOverlays": true}'/><br />
+        <button onclick="readWMC(true);">read and merge</button><br />
+        <button onclick="pasteWMC();">try with another WMC document</button><br />
         <textarea id="wmc">paste WMC doc here</textarea>
     <div id="docs">
         This is an example of parsing WMC documents. <br />

Copied: sandbox/ahocevar/playground/examples/wms-long-url.html (from rev 10919, trunk/openlayers/examples/wms-long-url.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wms-long-url.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wms-long-url.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>WMS with POST Requests to Avoid Long URLs</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+  </head>
+  <body>
+    <h1 id="title">WMS with POST Requests to Avoid Long URLs</h1>
+
+    <div id="tags">
+        sld, sld_body, post, iframe, advanced
+    </div>
+
+    <div id="shortdesc">Render tiles in IMG or IFRAME elements, depending on
+        the complexity of the GetMap request</div>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+        <p>The <code>maxGetUrlLength</code> property of the layer's
+            <code>tileOptions</code> option causes tiles to be requested using
+            HTTP POST when the length of the GET url would exceed the specified
+            length (2048 characters is recommended). In real life applications,
+            this happens often when using the SLD_BODY request parameter for
+            inline styling.
+        </p><p>
+            <input type="radio" name="group" id="longurl" checked="checked">
+            Long URL - POST requests
+            <br>
+            <input type="radio" name="group" id="shorturl">
+            Short URL - GET requests
+        </p><p>
+            View the <a href="wms-long-url.js" target="_blank">wms-long-url.js</a>
+            source to see how this is done.
+        </p>
+    </div>
+    <script src="../lib/OpenLayers.js"></script>
+    <script src="wms-long-url.js"></script>
+  </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/wms-long-url.js (from rev 10919, trunk/openlayers/examples/wms-long-url.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wms-long-url.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wms-long-url.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+// a long text that we set as dummy param (makeTheUrlLong) to make the url long
+var longText = new Array(205).join("1234567890");
+
+var map = new OpenLayers.Map( 'map' );
+var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+        "http://vmap0.tiles.osgeo.org/wms/vmap0",
+        {layers: 'basic', makeTheUrlLong: longText},
+        {tileOptions: {maxGetUrlLength: 2048}}
+);
+map.addLayer(layer);
+map.zoomToMaxExtent();
+
+// add behavior to dom elements
+document.getElementById("longurl").onclick = function() {
+    layer.mergeNewParams({makeTheUrlLong: longText})
+}
+document.getElementById("shorturl").onclick = function() {
+    layer.mergeNewParams({makeTheUrlLong: null})
+}

Modified: sandbox/ahocevar/playground/examples/wms-untiled.html
===================================================================
--- sandbox/ahocevar/playground/examples/wms-untiled.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wms-untiled.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -13,7 +13,7 @@
             map = new OpenLayers.Map( 'map' );
             layer = new OpenLayers.Layer.WMS(
                 "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'},
                 {singleTile: true}
             );
@@ -28,6 +28,7 @@
     <h1 id="title"> WMS Untiled Example</h1>
 
     <div id="tags">
+        singletile, tile
     </div>
         <p id="shortdesc">
             Shows an example of an "untiled" WMS layer, which requests a single

Copied: sandbox/ahocevar/playground/examples/wms-v13.html (from rev 10919, trunk/openlayers/examples/wms-v13.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wms-v13.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wms-v13.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, map2;
+
+        function init(){
+            // clear array to simulate a wrong axis order request
+            map = new OpenLayers.Map( 'map' );
+            var layer = new OpenLayers.Layer.WMS(
+                "OpenLayers WMS",
+                "http://demo.cubewerx.com/demo/cubeserv/cubeserv.cgi?",
+                {layers: 'Foundation.GTOPO30', version: '1.3.0'},
+                {singleTile: true, yx: []}
+            );
+            map.addLayer(layer);
+
+            map.zoomToMaxExtent();
+
+            map2 = new OpenLayers.Map( 'map2' );
+            var layer2 = new OpenLayers.Layer.WMS(
+                "OpenLayers WMS",
+                "http://demo.cubewerx.com/demo/cubeserv/cubeserv.cgi?",
+                {layers: 'Foundation.GTOPO30', version: '1.3.0'},
+                {singleTile: true}
+            );
+            map2.addLayer(layer2);
+
+            map2.zoomToMaxExtent();
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title"> WMS version 1.3 (axis order) Example</h1>
+
+    <div id="tags">
+        axis order, wms 1.3
+    </div>
+        <p id="shortdesc">
+            Shows an example of the influence of axis order on WMS 1.3 GetMap requests.
+        </p>
+        <div id="map" class="smallmap"></div>
+        <div id="map2" class="smallmap"></div>
+        <div id="docs">
+        WMS version 1.3 introduced the axis order sequence, so that for e.g. EPSG:4326 the bbox coordinate
+        values need to be flipped (LatLon instead of LonLat). The first map uses the incorrect (WMS 1.1) axis
+        order against a WMS 1.3 service, resulting in corrupted maps. The second map shows how to correctly
+        request a map in EPSG:4326 against a WMS 1.3 service.
+        </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/examples/wms.html
===================================================================
--- sandbox/ahocevar/playground/examples/wms.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wms.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,7 +12,7 @@
         function init(){
             map = new OpenLayers.Map( 'map' );
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
 
             map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
@@ -24,6 +24,7 @@
     <h1 id="title">WMS Example</h1>
 
     <div id="tags">
+        wms, layer, singletile
     </div>
     <p id="shortdesc">
         Shows the basic use of openlayers using a WMS layer

Modified: sandbox/ahocevar/playground/examples/wmst.html
===================================================================
--- sandbox/ahocevar/playground/examples/wmst.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wmst.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,13 +10,13 @@
             map = new OpenLayers.Map('map');
 
             var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'} );
 
             var jpl_wms = new OpenLayers.Layer.WMS( "NASA Global Mosaic",
                 "http://t1.hypercube.telascience.org/cgi-bin/landsat7", 
                 {layers: "landsat7"});
 
-            ia_wms = new OpenLayers.Layer.WMS("Nexrad","http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?",{layers:"nexrad-n0r-wmst",transparent:true,format:'image/png',time:"2005-08-29T13:00:00Z"});
+            ia_wms = new OpenLayers.Layer.WMS("Nexrad","http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi?",{layers:"nexrad-n0r-wmst",transparent:true,format:'image/png',time:"2005-08-29T13:00:00Z"});
 
             jpl_wms.setVisibility(false);
 
@@ -38,6 +38,7 @@
   <body onload="init()">
      <h1 id="title"> WMS Time Example</h1>
         <div id="tags">
+            wmst, wms-t
         </div>
         <p id="shortdesc">
             Shows the use of the layer WMS-T (time) layer</a>

Copied: sandbox/ahocevar/playground/examples/wmts-capabilities.html (from rev 10919, trunk/openlayers/examples/wmts-capabilities.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts-capabilities.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts-capabilities.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers WMTS Capabilities Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css"/>
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/Firebug/firebug.js"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="wmts-capabilities.js"></script>
+        <style>
+            .olControlAttribution {
+                bottom: 5px;
+            }
+        </style>
+    </head>
+    <body onload="init();">
+        <h1 id="title">Web Map Tile Service (WMTS) Capabilities Parsing</h1>
+        <div id="tags">
+            wmts, capabilities, getcapabilities
+        </div>         
+        <p id="shortdesc">
+            The WMTS Capabilities format allows for parsing of capabilities
+            documents from OGC Web Map Tile Service (WMTS) version 1.0.0 
+            implementations.
+        </p>
+        
+        <div id="map" class="smallmap"></div>
+        
+        <div id="docs">
+            <p>
+                This example creates an OpenLayers.Layer.WMTS layer to based
+                on the results of parsing a capabilities doc with the
+                OpenLayers.Format.WMTSCapabilities parser.
+            </p><p>
+                See the <a href="wmts-capabilities.js" target="_blank">
+                wmts-capabilities.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/wmts-capabilities.js (from rev 10919, trunk/openlayers/examples/wmts-capabilities.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts-capabilities.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts-capabilities.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,64 @@
+OpenLayers.ProxyHost = "/proxy/?url=";
+
+var map, format;
+
+function init() {
+    
+    format = new OpenLayers.Format.WMTSCapabilities({
+        /**
+         * This particular service is not in compliance with the WMTS spec and
+         * is providing coordinates in y, x order regardless of the CRS.  To
+         * work around this, we can provide the format a table of CRS URN that 
+         * should be considered y, x order.  These will extend the defaults on 
+         * the format.
+         */
+        yx: {
+            "urn:ogc:def:crs:EPSG::900913": true
+        }
+    });
+
+    OpenLayers.Request.GET({
+        url: "http://v2.suite.opengeo.org/geoserver/gwc/service/wmts",
+        params: {
+            SERVICE: "WMTS",
+            VERSION: "1.0.0",
+            REQUEST: "GetCapabilities"
+        },
+        success: function(request) {
+            var doc = request.responseXML;
+            if (!doc || !doc.documentElement) {
+                doc = request.responseText;
+            }
+            var capabilities = format.read(doc);
+            var layer = format.createLayer(capabilities, {
+                layer: "medford:buildings",
+                matrixSet: "EPSG:900913",
+                format: "image/png",
+                opacity: 0.7,
+                isBaseLayer: false
+            });
+            map.addLayer(layer);
+        }, 
+        failure: function() {
+            alert("Trouble getting capabilities doc");
+            OpenLayers.Console.error.apply(OpenLayers.Console, arguments);
+        }
+    })
+    
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: "EPSG:900913",
+        units: "m",
+        maxExtent: new OpenLayers.Bounds(
+            -20037508.34, -20037508.34, 20037508.34, 20037508.34
+        ),
+        maxResolution: 156543.0339
+    });    
+    
+    var osm = new OpenLayers.Layer.OSM();
+
+    map.addLayer(osm);
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.setCenter(new OpenLayers.LonLat(-13677832, 5213272), 13);
+    
+}

Copied: sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.html (from rev 10919, trunk/openlayers/examples/wmts-getfeatureinfo.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers WMTS GetFeatureInfo Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css"/>
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/Firebug/firebug.js"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="wmts-getfeatureinfo.js"></script>
+        <style>
+            .olControlAttribution {
+                bottom: 5px;
+            }
+
+            table.featureInfo, table.featureInfo td, table.featureInfo th {
+                border: 1px solid #ddd;
+                border-collapse: collapse;
+                margin: 0;
+                padding: 0;
+                font-size: 80%;
+                padding: .1em .1em;
+            }
+            table.featureInfo th {
+                padding: .2em .2em;
+                font-weight: bold;
+                background: #eee;
+            }
+            table.featureInfo td {
+                background: #fff;
+            }
+            table.featureInfo tr.odd td {
+                background: #eee;
+            }
+            table.featureInfo caption {
+                text-align: left;
+                font-size: 100%;
+                font-weight: bold;
+                text-transform: uppercase;
+                padding: .1em .2em;
+            }
+
+        </style>
+    </head>
+    <body onload="init();">
+        <h1 id="title">WMTS GetFeatureInfo Control</h1>
+        <div id="tags">
+            wmts, tile, cache, getfeatureinfo
+        </div>        
+        <p id="shortdesc">
+            The WMTSGetFeatureInfo control allows retrieval of information about
+            features displayed in a WMTS layer.
+        </p>
+        
+        <div id="map" class="smallmap"></div>
+        <input id="drill" type="checkbox" checked="checked">
+        <label for="drill">drill down</label>
+        <div id="docs">
+            <p>
+                This example uses an OpenLayers.Control.WMTSGetFeatureInfo
+                control layer to access information from WMTS layers.  The
+                control is activated and configured to request feature 
+                information when you click on the map.  If the control's 
+                drillDown property is set to true, multiple layers can be 
+                queried.
+            </p><p>
+                See the <a href="wmts-getfeatureinfo.js" target="_blank">
+                wmts-getfeatureinfo.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.js (from rev 10919, trunk/openlayers/examples/wmts-getfeatureinfo.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts-getfeatureinfo.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,99 @@
+OpenLayers.ProxyHost = "/proxy/?url=";
+var map, control, popups = {};
+
+function init() {
+    
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: "EPSG:900913",
+        units: "m",
+        maxExtent: new OpenLayers.Bounds(
+            -20037508.34, -20037508.34, 20037508.34, 20037508.34
+        ),
+        maxResolution: 156543.0339
+    });    
+    
+    var osm = new OpenLayers.Layer.OSM();
+
+    // If tile matrix identifiers differ from zoom levels (0, 1, 2, ...)
+    // then they must be explicitly provided.
+    var matrixIds = new Array(26);
+    for (var i=0; i<26; ++i) {
+        matrixIds[i] = "EPSG:900913:" + i;
+    }
+
+    var zoning = new OpenLayers.Layer.WMTS({
+        name: "zoning",
+        url: "http://v2.suite.opengeo.org/geoserver/gwc/service/wmts/",
+        layer: "medford:zoning",
+        matrixSet: "EPSG:900913",
+        matrixIds: matrixIds,
+        format: "image/png",
+        style: "_null",
+        opacity: 0.7,
+        isBaseLayer: false
+    });
+    var buildings = new OpenLayers.Layer.WMTS({
+        name: "building",
+        url: "http://v2.suite.opengeo.org/geoserver/gwc/service/wmts/",
+        layer: "medford:buildings",
+        matrixSet: "EPSG:900913",
+        matrixIds: matrixIds,
+        format: "image/png",
+        style: "_null",
+        isBaseLayer: false
+    });
+
+    map.addLayers([osm, zoning, buildings]);
+    
+    // create WMTS GetFeatureInfo control
+    control = new OpenLayers.Control.WMTSGetFeatureInfo({
+        drillDown: true,
+        queryVisible: true,
+        eventListeners: {
+            getfeatureinfo: function(evt) {
+                var text;
+                var match = evt.text.match(/<body[^>]*>([\s\S]*)<\/body>/);
+                if (match && !match[1].match(/^\s*$/)) {
+                    text = match[1];
+                } else {
+                    text = "No " + evt.layer.name + " features in that area.<br>";
+                }
+                var popupId = evt.xy.x + "," + evt.xy.y;
+                var popup = popups[popupId];
+                if (!popup || !popup.map) {
+                    popup = new OpenLayers.Popup.FramedCloud(
+                        popupId, 
+                        map.getLonLatFromPixel(evt.xy),
+                        null,
+                        " ",
+                        null,
+                        true,
+                        function(evt) {
+                            delete popups[this.id];
+                            this.hide();
+                            OpenLayers.Event.stop(evt);
+                        }
+                    );
+                    popups[popupId] = popup;
+                    map.addPopup(popup, true);
+                }
+                popup.setContentHTML(popup.contentHTML + text);
+                popup.show();
+            }
+        }
+    });
+    map.addControl(control);
+    control.activate();
+    
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.setCenter(new OpenLayers.LonLat(-13678519, 5212803), 15);
+    
+    var drill = document.getElementById("drill");
+    drill.checked = true;
+    drill.onchange = function() {
+        control.drillDown = drill.checked;
+    };
+}
+
+OpenLayers.Popup.FramedCloud.prototype.maxSize = new OpenLayers.Size(350, 200);

Copied: sandbox/ahocevar/playground/examples/wmts.html (from rev 10919, trunk/openlayers/examples/wmts.html)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>OpenLayers WMTS Example</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css"/>
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/Firebug/firebug.js"></script>
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="wmts.js"></script>
+        <style>
+            .olControlAttribution {
+                bottom: 5px;
+            }
+        </style>
+    </head>
+    <body onload="init();">
+        <h1 id="title">Web Map Tile Service (WMTS) Layer</h1>
+        <div id="tags">
+            wmts
+        </div>         
+        <p id="shortdesc">
+            The WMTS layer allows viewing of tiles from a server implementing
+            the OGC Web Map Tile Service (WMTS) standard version 1.0.0.
+        </p>
+        
+        <div id="map" class="smallmap"></div>
+        
+        <div id="docs">
+            <p>
+                This example uses an OpenLayers.Layer.WMTS layer to display
+                cached tiles over an OSM layer in spherical mercator coordinates.
+            </p><p>
+                See the <a href="wmts.js" target="_blank">
+                wmts.js source</a> to see how this is done.
+            </p>
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/wmts.js (from rev 10919, trunk/openlayers/examples/wmts.js)
===================================================================
--- sandbox/ahocevar/playground/examples/wmts.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/wmts.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,40 @@
+var map;
+
+function init() {
+    
+    map = new OpenLayers.Map({
+        div: "map",
+        projection: "EPSG:900913",
+        units: "m",
+        maxExtent: new OpenLayers.Bounds(
+            -20037508.34, -20037508.34, 20037508.34, 20037508.34
+        ),
+        maxResolution: 156543.0339
+    });    
+    
+    var osm = new OpenLayers.Layer.OSM();
+
+    // If tile matrix identifiers differ from zoom levels (0, 1, 2, ...)
+    // then they must be explicitly provided.
+    var matrixIds = new Array(26);
+    for (var i=0; i<26; ++i) {
+        matrixIds[i] = "EPSG:900913:" + i;
+    }
+
+    var wmts = new OpenLayers.Layer.WMTS({
+        name: "Medford Buildings",
+        url: "http://v2.suite.opengeo.org/geoserver/gwc/service/wmts/",
+        layer: "medford:buildings",
+        matrixSet: "EPSG:900913",
+        matrixIds: matrixIds,
+        format: "image/png",
+        style: "_null",
+        opacity: 0.7,
+        isBaseLayer: false
+    });                
+
+    map.addLayers([osm, wmts]);
+    map.addControl(new OpenLayers.Control.LayerSwitcher());
+    map.setCenter(new OpenLayers.LonLat(-13677832, 5213272), 13);
+    
+}

Modified: sandbox/ahocevar/playground/examples/worldwind.html
===================================================================
--- sandbox/ahocevar/playground/examples/worldwind.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/worldwind.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,7 @@
             map = new OpenLayers.Map('map', {'maxResolution': .28125, tileSize: new OpenLayers.Size(512, 512)});
 
             ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'} );
+            "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'} );
 
             ww = new OpenLayers.Layer.WorldWind( "Bathy",
             "http://worldwind25.arc.nasa.gov/tile/tile.aspx?", 36, 4,
@@ -30,6 +30,7 @@
         <h1 id="title">WorldWind layers Example</h1>
 
         <div id="tags">
+            worldwind, tile
         </div>
         <p id="shortdesc">
             Shows the use of the Tiled WorldWind layers.

Modified: sandbox/ahocevar/playground/examples/wrapDateLine.html
===================================================================
--- sandbox/ahocevar/playground/examples/wrapDateLine.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/wrapDateLine.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,7 +9,7 @@
         function init(){
             map = new OpenLayers.Map( 'map', {maxResolution: 1.40625} );
             var mapserv = new OpenLayers.Layer.MapServer( "OpenLayers Basic",
-                        "http://labs.metacarta.com/wms/vmap0",
+                        "http://vmap0.tiles.osgeo.org/wms/vmap0",
                         {layers: 'basic'},
                         {wrapDateLine: true} );
 
@@ -25,11 +25,6 @@
                  transparent: "true", format: "image/png"},
                 {wrapDateLine: true, reproject: false});
 
-            /* TMS is broken, too */
-            tms = new OpenLayers.Layer.TMS( "OpenStreetMap",
-                    "http://labs.metacarta.com/wms-c/Basic.py/",
-                    {layername: 'osm-map', type:'png', wrapDateLine: true} );
-
             /* WW doesn't quite work yet */
             ww = new OpenLayers.Layer.WorldWind( "LANDSAT",
                     "http://worldwind25.arc.nasa.gov/tile/tile.aspx", 2.25, 4,
@@ -48,10 +43,9 @@
   <body onload="init()">
     <h1 id="title">Wrapping the Date Line</h1>
     <div id="tags">
-      Related to:
-        <a href="http://dev.openlayers.org/docs/OpenLayers/Layer/WMS.html">Layer.WMS</a>,
-        <a href="http://dev.openlayers.org/docs2/OpenLayers/Layer/MapServer.html">Layer.MapServer</a>,
-        <a href="http://dev.openlayers.org/docs2/OpenLayers/Layer.html#wrapDateLine">wrapDateLine</a>
+        WMS,
+        MapServer,
+        wrapDateLine
     </div>
 
     <p id="shortdesc">Shows how to work around dateline issues, by wrapping the dateline on a number of layer types.</p>
@@ -66,7 +60,7 @@
         </p>
     <pre id="code">
     var mapserv = new OpenLayers.Layer.MapServer( "OpenLayers Basic",
-                "http://labs.metacarta.com/wms/vmap0",
+                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                 {layers: 'basic'},
                 <b>{wrapDateLine: true}</b> );
     </pre>

Modified: sandbox/ahocevar/playground/examples/xhtml.html
===================================================================
--- sandbox/ahocevar/playground/examples/xhtml.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/xhtml.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,6 +11,7 @@
     <h1 id="title">XHTML Example</h1>
 
     <div id="tags">
+        xhtml
     </div>
     <p id="shortdesc">
         Shows openlayers running in a XHTML 1.0 Strict Doctype
@@ -20,7 +21,7 @@
   <script defer="defer" type="text/javascript">
     var map = new OpenLayers.Map('map');
     var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-        "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+        "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
     map.addLayer(wms);
     map.zoomToMaxExtent();
   </script>

Modified: sandbox/ahocevar/playground/examples/xml.html
===================================================================
--- sandbox/ahocevar/playground/examples/xml.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/xml.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -112,6 +112,7 @@
             <h1 id="title">XML Format Example</h1>
 
             <div id="tags">
+                xml
             </div>
 
             <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/xyz-esri.html
===================================================================
--- sandbox/ahocevar/playground/examples/xyz-esri.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/xyz-esri.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,7 +21,9 @@
   <body onload="init()">
     <h1 id="title">Basic ESRI Map Cache Example</h1>
 
-    <div id="tags"></div>
+    <div id="tags">
+        XYZ, layer, tile
+    </div>
 
     <div id="shortdesc">Show a Simple ESRI map using the layer from <a href="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/ESRI_LandBase_WebMercator/MapServer">ESRI's server</a>. </div>
 

Copied: sandbox/ahocevar/playground/examples/xyz-offset.html (from rev 10919, trunk/openlayers/examples/xyz-offset.html)
===================================================================
--- sandbox/ahocevar/playground/examples/xyz-offset.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/xyz-offset.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title>OpenLayers XYZ with Offset</title>
+        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="style.css" type="text/css" />
+        <script src="../lib/OpenLayers.js"></script>
+        <script src="xyz-offset.js"></script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">XYZ Layer with Offset</h1>
+        <div id="tags">
+            XYZ, layer, tile
+        </div>        
+        <div id="shortdesc">Using a limited set of levels from an XYZ layer with zoomOffset.</div>
+        
+        <div id="map" class="smallmap"></div>
+        
+        <div id="docs">
+            <p>
+                The XYZ layer allows a zoomOffset to be set if you want to have
+                a maximum resolution for the map that differs from the maxiumum
+                resolution of the cached tiles.  This example uses only 6 of the
+                levels in the cache, starting with the ninth level (index of 8)
+                in the cache.  To do this, the layer is constructed with a
+                zoomOffset of 8.  When the map zoom level is zero, the level
+                with index 8 will be requested from the cache.
+            </p>
+            <p>
+                See the <a href="xyz-offset.js" target="_blank">
+                xyz-offset.js source</a> to see how this is done.
+            </p>        
+        </div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/examples/xyz-offset.js (from rev 10919, trunk/openlayers/examples/xyz-offset.js)
===================================================================
--- sandbox/ahocevar/playground/examples/xyz-offset.js	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/xyz-offset.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,37 @@
+var map, layer;
+
+// if tiles are not available, hide images
+//OpenLayers.Util.onImageLoadError = function() {
+//    this.style.display = "none";
+//}
+
+// called on body load
+function init() {
+
+    var extent = new OpenLayers.Bounds(
+        -13758743.4295939,  5591455.28887228, -13531302.3472101 , 5757360.4178881
+    );
+
+    map = new OpenLayers.Map({
+        div: "map",
+        maxExtent: new OpenLayers.Bounds(
+            -128 * 156543.0339, -128 * 156543.0339,
+            128 * 156543.0339, 128 * 156543.0339
+        ),
+        restrictedExtent: extent,
+        maxResolution: 611.496226171875, // corresponds to level 8 in the cache
+        numZoomLevels: 6,
+        projection: new OpenLayers.Projection("EPSG:900913"),
+        units: "m",
+        layers: [
+            new OpenLayers.Layer.XYZ(
+                "ESRI",
+                "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/ESRI_LandBase_WebMercator/MapServer/tile/${z}/${y}/${x}",
+                {zoomOffset: 8} // since our map maxResolution differs from cache max resolution
+            )
+        ]
+    });
+
+    map.zoomToExtent(extent);
+
+}

Modified: sandbox/ahocevar/playground/examples/yahoo.html
===================================================================
--- sandbox/ahocevar/playground/examples/yahoo.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/yahoo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -16,7 +16,7 @@
             map.addLayer(yahooLayer);
 
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+                "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
             map.addLayer(layer);
 
             map.setCenter(new OpenLayers.LonLat(-5, 40), 4);
@@ -28,6 +28,7 @@
     <h1 id="title">Yahoo Base Layer Example</h1>
 
         <div id="tags">
+            yahoo, layer
         </div>
 
         <p id="shortdesc">

Modified: sandbox/ahocevar/playground/examples/zoomLevels.html
===================================================================
--- sandbox/ahocevar/playground/examples/zoomLevels.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/examples/zoomLevels.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,7 +32,7 @@
 
 
             layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
-                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'});
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'});
             map.addLayer(layer);
 
 
@@ -45,6 +45,7 @@
     <h1 id="title">Zoom Level</h1>
 
     <div id="tags">
+        zoom, zoomlevel, resolution, scale, cleanup
     </div>
 
     <p id="shortdesc">

Copied: sandbox/ahocevar/playground/examples/zoomify.html (from rev 10919, trunk/openlayers/examples/zoomify.html)
===================================================================
--- sandbox/ahocevar/playground/examples/zoomify.html	                        (rev 0)
+++ sandbox/ahocevar/playground/examples/zoomify.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,72 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Zoomify Example</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+        var zoomify_width = 8001;
+		var zoomify_height = 6943;
+		var zoomify_url = "http://almor.mzk.cz/moll/AA22/0103/";
+
+        var map, zoomify;
+
+        function init(){
+	       /* First we initialize the zoomify pyramid (to get number of tiers) */
+	        var zoomify = new OpenLayers.Layer.Zoomify( "Zoomify", zoomify_url, 
+		  		new OpenLayers.Size( zoomify_width, zoomify_height ) );
+
+	       /* Map with raster coordinates (pixels) from Zoomify image */
+	        var options = {
+	            controls: [],
+	            maxExtent: new OpenLayers.Bounds(0, 0, zoomify_width, zoomify_height),
+	            maxResolution: Math.pow(2, zoomify.numberOfTiers-1 ),
+	            numZoomLevels: zoomify.numberOfTiers,
+	            units: 'pixels'
+	        };
+
+	        map = new OpenLayers.Map("map", options);
+	        map.addLayer(zoomify);
+
+	        map.addControl(new OpenLayers.Control.MousePosition());
+	        map.addControl(new OpenLayers.Control.PanZoomBar());
+	        map.addControl(new OpenLayers.Control.MouseDefaults());
+	        map.addControl(new OpenLayers.Control.KeyboardDefaults());
+
+            map.setBaseLayer(zoomify);
+	        map.zoomToMaxExtent();
+        };
+    </script>
+  </head>
+  <body onload="init()">
+      <h1 id="title">Zoomify Layer Example</h1>
+
+    <div id="tags">
+        zoomify, layer
+    </div>
+
+    <p id="shortdesc">
+        Demo of a layer with Zoomify tiles.
+    </p>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+	    <p>
+	    Demonstration of the Zoomify layer in OpenLayers.<br />
+	 	You can have a look at <a href="http://almor.mzk.cz/moll/AA22/103.html">Zoomify viewer for this picture</a>, which is using the same <a href="http://almor.mzk.cz/moll/AA22/0103/">tiles</a>.
+	    </p>
+		<p>
+		For change to our own image you have to specify 'url' (zoomifyImagePath in Zoomify terminology) and 'size' ('width' and 'height' from ImageProperty.xml file).<br />
+		Custom tiles can be easily generated with original <a href="http://www.zoomify.com/">Zoomify software</a> like with freely available <a href="http://www.zoomify.com/express.htm">ZoomifyerEZ</a> or with Adobe PhotoShop CS3 (it has built in support for export into Zoomify tiles).<br />
+		There is also a <a href="http://sourceforge.net/projects/zoomifyimage/">ZoomifyImage SourceForge Project</a>, a tile cutter available under GPL license.<br />
+		Zoomify tiles can be also served dynamically on the server side from JPEG2000 masters using <a href="http://dltj.org/article/introducing-j2ktilerenderer/">J2KTileRender</a> with available integration for DSpace and soon for Fedora Digital Repository.<br/>
+		<a href="http://iipimage.sourceforge.net/">IIPImage server</a> can serve Zoomify tiles dynamically from TIFF files.
+		</p>
+		<p>
+		Development of the Zoomify support for OpenLayers was supported from the grant <a href="http://www.oldmapsonline.org/">Old Maps Online</a>.
+        </p>
+    </div>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/img/cloud-popup-relative.png
===================================================================
(Binary files differ)

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Ajax.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Ajax.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Ajax.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -43,7 +44,7 @@
 };
 
 /** 
- * APIFunction: loadURL
+ * APIFunction: OpenLayers.loadURL
  * Background load a document.  For more flexibility in using XMLHttpRequest,
  *     see the <OpenLayers.Request> methods.
  *
@@ -84,7 +85,7 @@
 };
 
 /** 
- * Function: parseXMLString
+ * Function: OpenLayers.parseXMLString
  * Parse XML into a doc structure
  * 
  * Parameters:

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Bounds.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Bounds.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Bounds.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -128,11 +129,18 @@
     /**
      * APIMethod: toArray
      *
+     * Parameters:
+     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
+     *
      * Returns:
      * {Array} array of left, bottom, right, top
      */
-    toArray: function() {
-        return [this.left, this.bottom, this.right, this.top];
+    toArray: function(reverseAxisOrder) {
+        if (reverseAxisOrder === true) {
+            return [this.bottom, this.left, this.top, this.right];
+        } else {
+            return [this.left, this.bottom, this.right, this.top];
+        }
     },    
 
     /** 
@@ -141,22 +149,26 @@
      * Parameters:
      * decimal - {Integer} How many significant digits in the bbox coords?
      *                     Default is 6
+     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
      * 
      * Returns:
      * {String} Simple String representation of bounds object.
      *          (ex. <i>"5,42,10,45"</i>)
      */
-    toBBOX:function(decimal) {
+    toBBOX:function(decimal, reverseAxisOrder) {
         if (decimal== null) {
             decimal = 6; 
         }
         var mult = Math.pow(10, decimal);
-        var bbox = Math.round(this.left * mult) / mult + "," + 
-                   Math.round(this.bottom * mult) / mult + "," + 
-                   Math.round(this.right * mult) / mult + "," + 
-                   Math.round(this.top * mult) / mult;
-
-        return bbox;
+        var xmin = Math.round(this.left * mult) / mult;
+        var ymin = Math.round(this.bottom * mult) / mult;
+        var xmax = Math.round(this.right * mult) / mult;
+        var ymax = Math.round(this.top * mult) / mult;
+        if (reverseAxisOrder === true) {
+            return ymin + "," + xmin + "," + ymax + "," + xmax;
+        } else {
+            return xmin + "," + ymin + "," + xmax + "," + ymax;
+        }
     },
  
     /**
@@ -254,8 +266,6 @@
         if(origin == null){
             origin = this.getCenterLonLat();
         }
-
-        var bounds = [];
         
         var origx,origy;
 
@@ -468,7 +478,7 @@
      * 
      * bounds - {<OpenLayers.Bounds>} The target bounds.
      * partial - {Boolean} If any of the target corners is within this bounds
-     *     consider the bounds contained.  Default is false.  If true, the
+     *     consider the bounds contained.  Default is false.  If false, the
      *     entire target bounds must be contained within this bounds.
      * inclusive - {Boolean} Treat shared edges as contained.  Default is
      *     true.

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Class.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Class.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Class.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -22,48 +23,22 @@
  *
  */
 OpenLayers.Class = function() {
-    var Class = function() {
-        /**
-         * This following condition can be removed at 3.0 - this is only for
-         * backwards compatibility while the Class.inherit method is still
-         * in use.  So at 3.0, the following three lines would be replaced with
-         * simply:
-         * this.initialize.apply(this, arguments);
-         */
-        if (arguments && arguments[0] != OpenLayers.Class.isPrototype) {
-            this.initialize.apply(this, arguments);
-        }
-    };
-    var extended = {};
-    var parent, initialize;
-    for(var i=0, len=arguments.length; i<len; ++i) {
-        if(typeof arguments[i] == "function") {
-            // make the class passed as the first argument the superclass
-            if(i == 0 && len > 1) {
-                initialize = arguments[i].prototype.initialize;
-                // replace the initialize method with an empty function,
-                // because we do not want to create a real instance here
-                arguments[i].prototype.initialize = function() {};
-                // the line below makes sure that the new class has a
-                // superclass
-                extended = new arguments[i];
-                // restore the original initialize method
-                if(initialize === undefined) {
-                    delete arguments[i].prototype.initialize;
-                } else {
-                    arguments[i].prototype.initialize = initialize;
-                }
-            }
-            // get the prototype of the superclass
-            parent = arguments[i].prototype;
-        } else {
-            // in this case we're extending with the prototype
-            parent = arguments[i];
-        }
-        OpenLayers.Util.extend(extended, parent);
+    var len = arguments.length;
+    var P = arguments[0];
+    var F = arguments[len-1];
+
+    var C = typeof F.initialize == "function" ?
+        F.initialize :
+        function(){ P.apply(this, arguments); };
+
+    if (len > 1) {
+        var newArgs = [C, P].concat(
+                Array.prototype.slice.call(arguments).slice(1, len-1), F);
+        OpenLayers.inherit.apply(null, newArgs);
+    } else {
+        C.prototype = F;
     }
-    Class.prototype = extended;
-    return Class;
+    return C;
 };
 
 /**
@@ -88,7 +63,6 @@
     };
 };
 
-
 /**
  * APIFunction: inherit
  * *Deprecated*.  Old method to inherit from one or more OpenLayers style
@@ -100,15 +74,35 @@
  * Returns:
  * An object prototype
  */
-OpenLayers.Class.inherit = function () {
-    var superClass = arguments[0];
-    var proto = new superClass(OpenLayers.Class.isPrototype);
-    for (var i=1, len=arguments.length; i<len; i++) {
-        if (typeof arguments[i] == "function") {
-            var mixin = arguments[i];
-            arguments[i] = new mixin(OpenLayers.Class.isPrototype);
-        }
-        OpenLayers.Util.extend(proto, arguments[i]);
-    }
-    return proto;
+OpenLayers.Class.inherit = function (P) {
+    var C = function() {
+       P.call(this);
+    };
+    var newArgs = [C].concat(Array.prototype.slice.call(arguments));
+    OpenLayers.inherit.apply(null, newArgs);
+    return C.prototype;
 };
+
+/**
+ * Function: OpenLayers.inherit
+ *
+ * Parameters:
+ * C - {Object} the class that inherits
+ * P - {Object} the superclass to inherit from
+ *
+ * In addition to the mandatory C and P parameters, an arbitrary number of
+ * objects can be passed, which will extend C.
+ */
+OpenLayers.inherit = function(C, P) {
+   var F = function() {};
+   F.prototype = P.prototype;
+   C.prototype = new F;
+   var i, l, o;
+   for(i=2, l=arguments.length; i<l; i++) {
+       o = arguments[i];
+       if(typeof o === "function") {
+           o = o.prototype;
+       }
+       OpenLayers.Util.extend(C.prototype, o);
+   }
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Element.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Element.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Element.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -47,7 +48,9 @@
     hide: function() {
         for (var i=0, len=arguments.length; i<len; i++) {
             var element = OpenLayers.Util.getElement(arguments[i]);
-            element.style.display = 'none';
+            if (element) {
+                element.style.display = 'none';
+            }
         }
     },
 
@@ -61,7 +64,9 @@
     show: function() {
         for (var i=0, len=arguments.length; i<len; i++) {
             var element = OpenLayers.Util.getElement(arguments[i]);
-            element.style.display = '';
+            if (element) {
+                element.style.display = '';
+            }
         }
     },
 
@@ -93,6 +98,7 @@
 
     /**
      * APIFunction: getDimensions
+     * *Deprecated*. Returns dimensions of the element passed in.
      *  
      * Parameters:
      * element - {DOMElement}
@@ -112,12 +118,13 @@
         var els = element.style;
         var originalVisibility = els.visibility;
         var originalPosition = els.position;
+        var originalDisplay = els.display;
         els.visibility = 'hidden';
         els.position = 'absolute';
         els.display = '';
         var originalWidth = element.clientWidth;
         var originalHeight = element.clientHeight;
-        els.display = 'none';
+        els.display = originalDisplay;
         els.position = originalPosition;
         els.visibility = originalVisibility;
         return {width: originalWidth, height: originalHeight};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/LonLat.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/LonLat.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/LonLat.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -92,7 +93,8 @@
             OpenLayers.Console.error(msg);
             return null;
         }
-        return new OpenLayers.LonLat(this.lon + lon, this.lat + lat);
+        return new OpenLayers.LonLat(this.lon + OpenLayers.Util.toFloat(lon), 
+                                     this.lat + OpenLayers.Util.toFloat(lat));
     },
 
     /** 
@@ -184,6 +186,5 @@
  */
 OpenLayers.LonLat.fromString = function(str) {
     var pair = str.split(",");
-    return new OpenLayers.LonLat(parseFloat(pair[0]), 
-                                 parseFloat(pair[1]));
+    return new OpenLayers.LonLat(pair[0], pair[1]);
 };

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Pixel.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Pixel.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Pixel.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Size.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Size.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes/Size.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/BaseTypes.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -162,7 +163,7 @@
      * Used to find tokens in a string.
      * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
      */
-    tokenRegEx:  /\${([\w.]+?)}/g,
+    tokenRegEx:  /\$\{([\w.]+?)\}/g,
     
     /**
      * Property: OpenLayers.String.numberRegEx
@@ -431,6 +432,38 @@
         return function(event) {
             return func.call(object, event || window.event);
         };
+    },
+    
+    /**
+     * APIFunction: False
+     * A simple function to that just does "return false". We use this to 
+     * avoid attaching anonymous functions to DOM event handlers, which 
+     * causes "issues" on IE<8.
+     * 
+     * Usage:
+     * document.onclick = OpenLayers.Function.False;
+     * 
+     * Returns:
+     * {Boolean}
+     */
+    False : function() {
+        return false;
+    },
+
+    /**
+     * APIFunction: True
+     * A simple function to that just does "return true". We use this to 
+     * avoid attaching anonymous functions to DOM event handlers, which 
+     * causes "issues" on IE<8.
+     * 
+     * Usage:
+     * document.onclick = OpenLayers.Function.True;
+     * 
+     * Returns:
+     * {Boolean}
+     */
+    True : function() {
+        return true;
     }
 };
 
@@ -487,7 +520,7 @@
      *     Array.prototype.filter extension to the ECMA-262 standard.  Where
      *     available, Array.prototype.filter will be used.
      *
-     * Based on well known example from http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
+     * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
      *
      * Parameters:
      * array - {Array} The array to be filtered.  This array is not mutated.
@@ -527,3 +560,122 @@
     }
     
 };
+
+/**
+ * Namespace: OpenLayers.Date
+ * Contains implementations of Date.parse and date.toISOString that match the 
+ *     ECMAScript 5 specification for parsing RFC 3339 dates.
+ *     http://tools.ietf.org/html/rfc3339
+ */
+OpenLayers.Date = {
+    
+    /**
+     * APIMethod: toISOString
+     * Generates a string representing a date.  The format of the string follows 
+     *     the profile of ISO 8601 for date and time on the Internet (see 
+     *     http://tools.ietf.org/html/rfc3339).  If the toISOString method is 
+     *     available on the Date prototype, that is used.  The toISOString
+     *     method for Date instances is defined in ECMA-262.
+     *
+     * Parameters:
+     * date - {Date} A date object.
+     *
+     * Returns:
+     * {String} A string representing the date (e.g. 
+     *     "2010-08-07T16:58:23.123Z").  If the date does not have a valid time
+     *     (i.e. isNaN(date.getTime())) this method returns the string "Invalid
+     *     Date".  The ECMA standard says the toISOString method should throw
+     *     RangeError in this case, but Firefox returns a string instead.  For
+     *     best results, use isNaN(date.getTime()) to determine date validity
+     *     before generating date strings.  
+     */
+    toISOString: (function() {
+        if ("toISOString" in Date.prototype) {
+            return function(date) {
+                return date.toISOString();
+            };
+        } else {
+            function pad(num, len) {
+                var str = num + "";
+                while (str.length < len) {
+                    str = "0" + str;
+                }
+                return str;
+            }
+            return function(date) {
+                var str;
+                if (isNaN(date.getTime())) {
+                    // ECMA-262 says throw RangeError, Firefox returns 
+                    // "Invalid Date"
+                    str = "Invalid Date";
+                } else {
+                    str = 
+                        date.getUTCFullYear() + "-" +
+                        pad(date.getUTCMonth() + 1, 2) + "-" +
+                        pad(date.getUTCDate(), 2) + "T" +
+                        pad(date.getUTCHours(), 2) + ":" +
+                        pad(date.getUTCMinutes(), 2) + ":" +
+                        pad(date.getUTCSeconds(), 2) + "." +
+                        pad(date.getUTCMilliseconds(), 3) + "Z";
+                }
+                return str;
+            };
+        }
+
+    })(),
+    
+    /**
+     * APIMethod: parse
+     * Generate a date object from a string.  The format for the string follows
+     *     the profile of ISO 8601 for date and time on the Internet (see 
+     *     http://tools.ietf.org/html/rfc3339).  If the parse method on 
+     *     the Date constructor returns a valid date for the given string,
+     *     that method is used.
+     *
+     * Parameters:
+     * str - {String} A string representing the date (e.g. 
+     *     "2010", "2010-08", "2010-08-07", "2010-08-07T16:58:23.123Z",
+     *     "2010-08-07T11:58:23.123-06").
+     * 
+     * Returns:
+     * {Date} A date object.  If the string could not be parsed, an invalid
+     *     date is returned (i.e. isNaN(date.getTime())).
+     */
+    parse: function(str) {
+        var date;
+        // first check if the native parse method can parse it
+        var elapsed = Date.parse(str);
+        if (!isNaN(elapsed)) {
+            date = new Date(elapsed);
+        } else {
+            var match = str.match(/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))?$/);
+            if (match && (match[1] || match[7])) { // must have at least year or time
+                var year = parseInt(match[1], 10) || 0;
+                var month = (parseInt(match[2], 10) - 1) || 0;
+                var day = parseInt(match[3], 10) || 1;
+                date = new Date(Date.UTC(year, month, day));
+                // optional time
+                var type = match[7];
+                if (type) {
+                    var hours = parseInt(match[4], 10);
+                    var minutes = parseInt(match[5], 10);
+                    var secFrac = parseFloat(match[6]);
+                    var seconds = secFrac | 0;
+                    var milliseconds = Math.round(1000 * (secFrac - seconds));
+                    date.setUTCHours(hours, minutes, seconds, milliseconds);
+                    // check offset
+                    if (type !== "Z") {
+                        var hoursOffset = parseInt(type, 10);
+                        var minutesOffset = parseInt(match[8]) || 0;
+                        var offset = -1000 * (60 * (hoursOffset * 60) + minutesOffset * 60);
+                        date = new Date(date.getTime() + offset);
+                    }
+                }
+            } else {
+                date = new Date("invalid");
+            }
+        }
+        return date;
+    }
+
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Console.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Console.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Console.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ArgParser.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ArgParser.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ArgParser.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Attribution.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Attribution.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Attribution.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -22,7 +23,7 @@
      * {String} String used to seperate layers.
      */
     separator: ", ",
-       
+    
     /**
      * Constructor: OpenLayers.Control.Attribution 
      * 
@@ -81,9 +82,13 @@
             for(var i=0, len=this.map.layers.length; i<len; i++) {
                 var layer = this.map.layers[i];
                 if (layer.attribution && layer.getVisibility()) {
-                    attributions.push( layer.attribution );
+                    // add attribution only if attribution text is unique
+                    if (OpenLayers.Util.indexOf(
+                                    attributions, layer.attribution) === -1) {
+                        attributions.push( layer.attribution );
+                    }
                 }
-            }  
+            } 
             this.div.innerHTML = attributions.join(this.separator);
         }
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Button.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Button.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Button.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Control.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/DragFeature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/DragFeature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/DragFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -65,6 +66,13 @@
     onComplete: function(feature, pixel) {},
 
     /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, mouse dragging will continue even if the
+     *     mouse cursor leaves the map viewport. Default is false.
+     */
+    documentDrag: false,
+    
+    /**
      * Property: layer
      * {<OpenLayers.Layer.Vector>}
      */
@@ -115,7 +123,9 @@
                     up: this.upFeature,
                     out: this.cancel,
                     done: this.doneDragging
-                }, this.dragCallbacks)
+                }, this.dragCallbacks), {
+                    documentDrag: this.documentDrag
+                }
             ),
             feature: new OpenLayers.Handler.Feature(
                 this, this.layer, OpenLayers.Util.extend({

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/DragPan.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/DragPan.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/DragPan.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -34,9 +35,16 @@
      *     panning the map again. Set this to increase dragging performance.
      *     Defaults to 25 milliseconds.
      */
-    interval: 25, 
+    interval: 25,
     
     /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, mouse dragging will continue even if the
+     *     mouse cursor leaves the map viewport. Default is false.
+     */
+    documentDrag: false,
+    
+    /**
      * Method: draw
      * Creates a Drag handler, using <panMap> and
      * <panMapDone> as callbacks.
@@ -46,7 +54,8 @@
                 "move": this.panMap,
                 "done": this.panMapDone
             }, {
-                interval: this.interval
+                interval: this.interval,
+                documentDrag: this.documentDrag
             }
         );
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/DrawFeature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/DrawFeature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/DrawFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -39,6 +40,13 @@
     EVENT_TYPES: ["featureadded"],
     
     /**
+     * APIProperty: multi
+     * {Boolean} Cast features to multi-part geometries before passing to the
+     *     layer.  Default is false.
+     */
+    multi: false,
+
+    /**
      * APIProperty: featureAdded
      * {Function} Called after each feature is added
      */
@@ -84,9 +92,12 @@
             this.callbacks
         );
         this.layer = layer;
+        this.handlerOptions = this.handlerOptions || {};
+        if (!("multi" in this.handlerOptions)) {
+            this.handlerOptions.multi = this.multi;
+        }
         var sketchStyle = this.layer.styleMap && this.layer.styleMap.styles.temporary;
         if(sketchStyle) {
-            this.handlerOptions = this.handlerOptions || {};
             this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
                 this.handlerOptions.layerOptions,
                 {styleMap: new OpenLayers.StyleMap({"default": sketchStyle})}

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/EditingToolbar.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/EditingToolbar.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/EditingToolbar.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/GetFeature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/GetFeature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/GetFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -14,7 +15,7 @@
  * Class: OpenLayers.Control.GetFeature
  * Gets vector features for locations underneath the mouse cursor. Can be
  *     configured to act on click, hover or dragged boxes. Uses an
- *     <OpenLayers.Protocol> that supports spatial filters (BBOX) to retrieve
+ *     <OpenLayers.Protocol> that supports spatial filters to retrieve
  *     features from a server and fires events that notify applications of the
  *     selected features. 
  *
@@ -59,10 +60,22 @@
 
     /**
      * APIProperty: click
-     * {Boolean} Use a click handler for selecting/unselecting features.
-     *     Default is true.
+     * {Boolean} Use a click handler for selecting/unselecting features. If
+     *     both <click> and <box> are set to true, the click handler takes
+     *     precedence over the box handler if a box with zero extent was
+     *     selected.  Default is true.
      */
     click: true,
+
+    /**
+     * APIProperty: single
+     * {Boolean} Tells whether select by click should select a single
+     *     feature. If set to false, all matching features are selected.
+     *     If set to true, only the best matching feature is selected.
+     *     This option has an effect only of the <click> option is set
+     *     to true. Default is true.
+     */
+    single: true,
     
     /**
      * APIProperty: clickout
@@ -80,10 +93,11 @@
 
     /**
      * APIProperty: clickTolerance
-     * {Integer} Tolerance for the BBOX query in pixels. This has the
+     * {Integer} Tolerance for the filter query in pixels. This has the
      *     same effect as the tolerance parameter on WMS GetFeatureInfo
      *     requests.  Will be ignored for box selections.  Applies only if
-     *     <click> is true.  Default is 5.
+     *     <click> or <hover> is true.  Default is 5.  Note that this not
+     *     only affects requests on click, but also on hover.
      */
     clickTolerance: 5,
     
@@ -95,14 +109,19 @@
 
     /**
      * APIProperty: box
-     * {Boolean} Allow feature selection by drawing a box.
+     * {Boolean} Allow feature selection by drawing a box. If set to
+     *     true set <click> to false to disable the click handler and
+     *     rely on the box handler only, even for "zero extent" boxes.
+     *     See the description of the <click> option for additional
+     *     information.  Default is false.
      */
     box: false,
     
     /**
      * APIProperty: maxFeatures
-     * {Integer} Maximum number of features to return from a query, if
-     *     supported by the <protocol>.  Default is 10.
+     * {Integer} Maximum number of features to return from a query in single mode
+     *     if supported by the <protocol>. This set of features is then used to
+     *     determine the best match client-side. Default is 10.
      */
     maxFeatures: 10,
     
@@ -142,6 +161,15 @@
     hoverResponse: null,
     
     /**
+     * Property: filterType
+     * {<String>} The type of filter to use when sending off a request. 
+     *     Possible values: 
+     *     OpenLayers.Filter.Spatial.<BBOX|INTERSECTS|WITHIN|CONTAINS>
+     *     Defaults to: OpenLayers.Filter.Spatial.BBOX
+     */
+    filterType: OpenLayers.Filter.Spatial.BBOX,
+
+    /**
      * Constant: EVENT_TYPES
      *
      * Supported event types:
@@ -151,6 +179,14 @@
      * featureselected - Triggered when <click> is true and a feature is
      *      selected. The event object has a feature property with the
      *      selected feature
+     * beforefeaturesselected - Triggered when <click> is true before a
+     *      set of features is selected. The event object is an array of
+     *      feature properties with the features about to be selected.  
+     *      Return false after receiving this event to discontinue processing
+     *      of all featureselected events and the featuresselected event.
+     * featuresselected - Triggered when <click> is true and a set of
+     *      features is selected.  The event object is an array of feature
+     *      properties of the selected features
      * featureunselected - Triggered when <click> is true and a feature is
      *      unselected. The event object has a feature property with the
      *      unselected feature
@@ -161,8 +197,9 @@
      * outfeature - Triggered when <hover> is true and the mouse moves
      *      moved away from a hover-selected feature
      */
-    EVENT_TYPES: ["featureselected", "featureunselected", "clickout",
-        "beforefeatureselected", "hoverfeature", "outfeature"],
+    EVENT_TYPES: ["featureselected", "featuresselected", "featureunselected", 
+        "clickout", "beforefeatureselected", "beforefeaturesselected", 
+        "hoverfeature", "outfeature"],
 
     /**
      * Constructor: OpenLayers.Control.GetFeature
@@ -170,7 +207,8 @@
      *
      * Parameters:
      * options - {Object} A configuration object which at least has to contain
-     *     a <protocol> property
+     *     a <protocol> property (if not, it has to be set before a request is
+     *     made)
      */
     initialize: function(options) {
         // concatenate events specific to vector with those from the base
@@ -189,8 +227,8 @@
         
         if(this.click) {
             this.handlers.click = new OpenLayers.Handler.Click(this,
-                {click: this.selectSingle}, this.handlerOptions.click || {})
-        };
+                {click: this.selectClick}, this.handlerOptions.click || {});
+        }
 
         if(this.box) {
             this.handlers.box = new OpenLayers.Handler.Box(
@@ -248,39 +286,17 @@
     },
     
     /**
-     * Method: unselectAll
-     * Unselect all selected features.  To unselect all except for a single
-     *     feature, set the options.except property to the feature.
-     *
-     * Parameters:
-     * options - {Object} Optional configuration object.
-     */
-    unselectAll: function(options) {
-        // we'll want an option to supress notification here
-        var feature;
-        for(var i=this.features.length-1; i>=0; --i) {
-            feature = this.features[i];
-            if(!options || options.except != feature) {
-                this.unselect(feature);
-            }
-        }
-    },
-
-    /**
-     * Method: selectSingle
+     * Method: selectClick
      * Called on click
      *
      * Parameters:
      * evt - {<OpenLayers.Event>} 
      */
-    selectSingle: function(evt) {
-        // Set the cursor to "wait" to tell the user we're working on their click.
-        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
-        
+    selectClick: function(evt) {
         var bounds = this.pixelToBounds(evt.xy);
         
         this.setModifiers(evt);
-        this.request(bounds, {single: true});
+        this.request(bounds, {single: this.single});
     },
 
     /**
@@ -291,6 +307,7 @@
      * position - {<OpenLayers.Bounds>}  
      */
     selectBox: function(position) {
+        var bounds;
         if (position instanceof OpenLayers.Bounds) {
             var minXY = this.map.getLonLatFromPixel(
                 new OpenLayers.Pixel(position.left, position.bottom)
@@ -298,13 +315,19 @@
             var maxXY = this.map.getLonLatFromPixel(
                 new OpenLayers.Pixel(position.right, position.top)
             );
-            var bounds = new OpenLayers.Bounds(
+            bounds = new OpenLayers.Bounds(
                 minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
             );
             
-            this.setModifiers(this.handlers.box.dragHandler.evt);
-            this.request(bounds);
+        } else {
+            if(this.click) {
+                // box without extent - let the click handler take care of it
+                return;
+            }
+            bounds = this.pixelToBounds(position);
         }
+        this.setModifiers(this.handlers.box.dragHandler.evt);
+        this.request(bounds);
     },
     
     /**
@@ -327,6 +350,8 @@
         if (this.hoverResponse) {
             this.protocol.abort(this.hoverResponse);
             this.hoverResponse = null;
+
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
         }
     },
 
@@ -347,15 +372,18 @@
     request: function(bounds, options) {
         options = options || {};
         var filter = new OpenLayers.Filter.Spatial({
-            type: OpenLayers.Filter.Spatial.BBOX,
+            type: this.filterType, 
             value: bounds
         });
         
+        // Set the cursor to "wait" to tell the user we're working.
+        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+
         var response = this.protocol.read({
             maxFeatures: options.single == true ? this.maxFeatures : undefined,
             filter: filter,
             callback: function(result) {
-                if(result.code == 1) {
+                if(result.success()) {
                     if(result.features.length) {
                         if(options.single == true) {
                             this.selectBestFeature(result.features,
@@ -421,7 +449,7 @@
             } else {
                 this.select(resultFeature || features);
             } 
-        };
+        }
     },
     
     /**
@@ -435,13 +463,13 @@
         this.modifiers = {
             multiple: this.multiple || (this.multipleKey && evt[this.multipleKey]),
             toggle: this.toggle || (this.toggleKey && evt[this.toggleKey])
-        }        
+        };        
     },
 
     /**
      * Method: select
      * Add feature to the hash of selected features and trigger the
-     * featureselected event.
+     * featureselected and featuresselected events.
      * 
      * Parameters:
      * features - {<OpenLayers.Feature.Vector>} or an array of features
@@ -454,24 +482,34 @@
             features = [features];
         }
         
-        var feature;
-        for(var i=0, len=features.length; i<len; ++i) {
-            feature = features[i];
-            if(this.features[feature.fid || feature.id]) {
-                if(this.modifiers.toggle) {
-                    this.unselect(this.features[feature.fid || feature.id]);
+        var cont = this.events.triggerEvent("beforefeaturesselected", {
+            features: features
+        });
+        if(cont !== false) {
+            var selectedFeatures = [];
+            var feature;
+            for(var i=0, len=features.length; i<len; ++i) {
+                feature = features[i];
+                if(this.features[feature.fid || feature.id]) {
+                    if(this.modifiers.toggle) {
+                        this.unselect(this.features[feature.fid || feature.id]);
+                    }
+                } else {
+                    cont = this.events.triggerEvent("beforefeatureselected", {
+                        feature: feature
+                    });
+                    if(cont !== false) {
+                        this.features[feature.fid || feature.id] = feature;
+                        selectedFeatures.push(feature);
+                
+                        this.events.triggerEvent("featureselected",
+                            {feature: feature});
+                    }
                 }
-            } else {
-                cont = this.events.triggerEvent("beforefeatureselected", {
-                    feature: feature
-                });
-                if(cont !== false) {
-                    this.features[feature.fid || feature.id] = feature;
-            
-                    this.events.triggerEvent("featureselected",
-                        {feature: feature});
-                }
             }
+            this.events.triggerEvent("featuresselected", {
+                features: selectedFeatures
+            });
         }
     },
     

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Control/Graticule.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Control/Graticule.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Graticule.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Graticule.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,373 @@
+/* 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/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Graticule
+ * The Graticule displays a grid of latitude/longitude lines reprojected on
+ * the map.  
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ *  
+ */
+OpenLayers.Control.Graticule = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map. Default is
+     *     true. 
+     */
+    autoActivate: true,
+    
+    /**
+    * APIProperty: intervals
+    * {Array(Float)} A list of possible graticule widths in degrees.
+    */
+    intervals: [ 45, 30, 20, 10, 5, 2, 1,
+                 0.5, 0.2, 0.1, 0.05, 0.01, 
+                 0.005, 0.002, 0.001 ],
+
+    /**
+     * APIProperty: displayInLayerSwitcher
+     * {Boolean} Allows the Graticule control to be switched on and off by 
+     *     LayerSwitcher control. Defaults is true.
+     */
+    displayInLayerSwitcher: true,
+
+    /**
+     * APIProperty: visible
+     * {Boolean} should the graticule be initially visible (default=true)
+     */
+    visible: true,
+
+    /**
+     * APIProperty: numPoints
+     * {Integer} The number of points to use in each graticule line.  Higher
+     * numbers result in a smoother curve for projected maps 
+     */
+    numPoints: 50,
+
+    /**
+     * APIProperty: targetSize
+     * {Integer} The maximum size of the grid in pixels on the map
+     */
+    targetSize: 200,
+
+    /**
+     * APIProperty: layerName
+     * {String} The name to be displayed in the layer switcher, default is set 
+     *     by {<OpenLayers.Lang>}.
+     */
+    layerName: null,
+
+    /**
+     * APIProperty: labelled
+     * {Boolean} Should the graticule lines be labelled?. default=true
+     */
+    labelled: true,
+
+    /**
+     * APIProperty: labelFormat
+     * {String} the format of the labels, default = 'dm'. See
+     * <OpenLayers.Util.getFormattedLonLat> for other options.
+     */
+    labelFormat: 'dm',
+
+    /**
+     * APIProperty: lineSymbolizer
+     * {symbolizer} the symbolizer used to render lines
+     */
+    lineSymbolizer: {
+                strokeColor: "#333",
+                strokeWidth: 1,
+                strokeOpacity: 0.5
+            },
+
+    /**
+     * APIProperty: labelSymbolizer
+     * {symbolizer} the symbolizer used to render labels
+     */
+     labelSymbolizer: {},
+
+    /**
+     * Property: gratLayer
+     * {OpenLayers.Layer.Vector} vector layer used to draw the graticule on
+     */
+    gratLayer: null,
+
+    /**
+     * Constructor: OpenLayers.Control.Graticule
+     * Create a new graticule control to display a grid of latitude longitude
+     * lines.
+     * 
+     * Parameters:
+     * options - {Object} An optional object whose properties will be used
+     *     to extend the control.
+     */
+    initialize: function(options) {
+        options = options || {};
+        options.layerName = options.layerName || OpenLayers.i18n("graticule");
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        this.labelSymbolizer.stroke = false;
+        this.labelSymbolizer.fill = false;
+        this.labelSymbolizer.label = "${label}";
+        this.labelSymbolizer.labelAlign = "${labelAlign}";
+        this.labelSymbolizer.labelXOffset = "${xOffset}";
+        this.labelSymbolizer.labelYOffset = "${yOffset}";
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        this.deactivate();        
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);        
+        if (this.gratLayer) {
+            this.gratLayer.destroy();
+            this.gratLayer = null;
+        }
+    },
+    
+    /**
+     * Method: draw
+     *
+     * initializes the graticule layer and does the initial update
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        if (!this.gratLayer) {
+            var gratStyle = new OpenLayers.Style({},{
+                rules: [new OpenLayers.Rule({'symbolizer':
+                    {"Point":this.labelSymbolizer,
+                     "Line":this.lineSymbolizer}
+                })]
+            });
+            this.gratLayer = new OpenLayers.Layer.Vector(this.layerName, {
+                styleMap: new OpenLayers.StyleMap({'default':gratStyle}),
+                visibility: this.visible,
+                displayInLayerSwitcher: this.displayInLayerSwitcher
+            });
+        }
+        return this.div;
+    },
+
+     /**
+     * APIMethod: activate
+     */
+    activate: function() {
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.map.addLayer(this.gratLayer);
+            this.map.events.register('moveend', this, this.update);     
+            this.update();
+            return true;            
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.map.events.unregister('moveend', this, this.update);
+            this.map.removeLayer(this.gratLayer);
+            return true;
+        } else {
+            return false;
+        }
+    },
+    /**
+     * Method: update
+     *
+     * calculates the grid to be displayed and actually draws it
+     * 
+     * Returns:
+     * {DOMElement}
+     */
+    update: function() {
+        //wait for the map to be initialized before proceeding
+        var mapBounds = this.map.getExtent();
+        if (!mapBounds) {
+            return;
+        }
+        
+        //clear out the old grid
+        this.gratLayer.destroyFeatures();
+        
+        //get the projection objects required
+        var llProj = new OpenLayers.Projection("EPSG:4326");
+        var mapProj = this.map.getProjectionObject();
+        var mapRes = this.map.getResolution();
+        
+        //if the map is in lon/lat, then the lines are straight and only one
+        //point is required
+        if (mapProj.proj && mapProj.proj.projName == "longlat") {
+            this.numPoints = 1;
+        }
+        
+        //get the map center in EPSG:4326
+        var mapCenter = this.map.getCenter(); //lon and lat here are really map x and y
+        var mapCenterLL = new OpenLayers.Pixel(mapCenter.lon, mapCenter.lat);
+        OpenLayers.Projection.transform(mapCenterLL, mapProj, llProj);
+        
+        /* This block of code determines the lon/lat interval to use for the
+         * grid by calculating the diagonal size of one grid cell at the map
+         * center.  Iterates through the intervals array until the diagonal
+         * length is less than the targetSize option.
+         */
+        //find lat/lon interval that results in a grid of less than the target size
+        var testSq = this.targetSize*mapRes;
+        testSq *= testSq;   //compare squares rather than doing a square root to save time
+        var llInterval;
+        for (var i=0; i<this.intervals.length; ++i) {
+            llInterval = this.intervals[i];   //could do this for both x and y??
+            var delta = llInterval/2;  
+            var p1 = mapCenterLL.offset(new OpenLayers.Pixel(-delta, -delta));  //test coords in EPSG:4326 space
+            var p2 = mapCenterLL.offset(new OpenLayers.Pixel( delta,  delta));
+            OpenLayers.Projection.transform(p1, llProj, mapProj); // convert them back to map projection
+            OpenLayers.Projection.transform(p2, llProj, mapProj);
+            var distSq = (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y);
+            if (distSq <= testSq) {
+                break;
+            }
+        }
+        //alert(llInterval);
+        
+        //round the LL center to an even number based on the interval
+        mapCenterLL.x = Math.floor(mapCenterLL.x/llInterval)*llInterval;
+        mapCenterLL.y = Math.floor(mapCenterLL.y/llInterval)*llInterval;
+        //TODO adjust for minutses/seconds?
+        
+        /* The following 2 blocks calculate the nodes of the grid along a 
+         * line of constant longitude (then latitiude) running through the
+         * center of the map until it reaches the map edge.  The calculation
+         * goes from the center in both directions to the edge.
+         */
+        //get the central longitude line, increment the latitude
+        var iter = 0;
+        var centerLonPoints = [mapCenterLL.clone()];
+        var newPoint = mapCenterLL.clone();
+        var mapXY;
+        do {
+            newPoint = newPoint.offset(new OpenLayers.Pixel(0,llInterval));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLonPoints.unshift(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        newPoint = mapCenterLL.clone();
+        do {          
+            newPoint = newPoint.offset(new OpenLayers.Pixel(0,-llInterval));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLonPoints.push(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        
+        //get the central latitude line, increment the longitude
+        iter = 0;
+        var centerLatPoints = [mapCenterLL.clone()];
+        newPoint = mapCenterLL.clone();
+        do {
+            newPoint = newPoint.offset(new OpenLayers.Pixel(-llInterval, 0));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLatPoints.unshift(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        newPoint = mapCenterLL.clone();
+        do {          
+            newPoint = newPoint.offset(new OpenLayers.Pixel(llInterval, 0));
+            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj);
+            centerLatPoints.push(newPoint);
+        } while (mapBounds.containsPixel(mapXY) && ++iter<1000);
+        
+        //now generate a line for each node in the central lat and lon lines
+        //first loop over constant longitude
+        var lines = [];
+        for(var i=0; i < centerLatPoints.length; ++i) {
+            var lon = centerLatPoints[i].x;
+            var pointList = [];
+            var labelPoint = null;
+            var latEnd = Math.min(centerLonPoints[0].y, 90);
+            var latStart = Math.max(centerLonPoints[centerLonPoints.length - 1].y, -90);
+            var latDelta = (latEnd - latStart)/this.numPoints;
+            var lat = latStart;
+            for(var j=0; j<= this.numPoints; ++j) {
+                var gridPoint = new OpenLayers.Geometry.Point(lon,lat);
+                gridPoint.transform(llProj, mapProj);
+                pointList.push(gridPoint);
+                lat += latDelta;
+                if (gridPoint.y >= mapBounds.bottom && !labelPoint) {
+                    labelPoint = gridPoint;
+                }
+            }
+            if (this.labelled) {
+                //keep track of when this grid line crosses the map bounds to set
+                //the label position
+                //labels along the bottom, add 10 pixel offset up into the map
+                //TODO add option for labels on top
+                var labelPos = new OpenLayers.Geometry.Point(labelPoint.x,mapBounds.bottom);
+                var labelAttrs = {
+                    value: lon,
+                    label: this.labelled?OpenLayers.Util.getFormattedLonLat(lon, "lon", this.labelFormat):"",
+                    labelAlign: "cb",
+                    xOffset: 0,
+                    yOffset: 2
+                }; 
+                this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));
+            }
+            var geom = new OpenLayers.Geometry.LineString(pointList);
+            lines.push(new OpenLayers.Feature.Vector(geom));
+        }
+        
+        //now draw the lines of constant latitude
+        for (var j=0; j < centerLonPoints.length; ++j) {
+            lat = centerLonPoints[j].y;
+            if (lat<-90 || lat>90) {  //latitudes only valid between -90 and 90
+                continue;
+            }
+            var pointList = [];
+            var lonStart = centerLatPoints[0].x;
+            var lonEnd = centerLatPoints[centerLatPoints.length - 1].x;
+            var lonDelta = (lonEnd - lonStart)/this.numPoints;
+            var lon = lonStart;
+            var labelPoint = null;
+            for(var i=0; i <= this.numPoints ; ++i) {
+                var gridPoint = new OpenLayers.Geometry.Point(lon,lat);
+                gridPoint.transform(llProj, mapProj);
+                pointList.push(gridPoint);
+                lon += lonDelta;
+                if (gridPoint.x < mapBounds.right) {
+                    labelPoint = gridPoint;
+                }
+            }
+            if (this.labelled) {
+                //keep track of when this grid line crosses the map bounds to set
+                //the label position
+                //labels along the right, 30 pixel offset left into the map
+                //TODO add option for labels on left
+                var labelPos = new OpenLayers.Geometry.Point(mapBounds.right, labelPoint.y); 
+                var labelAttrs = {
+                    value: lat,
+                    label: this.labelled?OpenLayers.Util.getFormattedLonLat(lat, "lat", this.labelFormat):"",
+                    labelAlign: "rb",
+                    xOffset: -2,
+                    yOffset: 2
+                }; 
+                this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));
+            }
+            var geom = new OpenLayers.Geometry.LineString(pointList);
+            lines.push(new OpenLayers.Feature.Vector(geom));
+          }
+          this.gratLayer.addFeatures(lines);
+    },
+    
+    CLASS_NAME: "OpenLayers.Control.Graticule"
+});
+

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/KeyboardDefaults.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/KeyboardDefaults.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/KeyboardDefaults.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,8 +1,8 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Control.js
  * @requires OpenLayers/Handler/Keyboard.js
@@ -22,6 +22,13 @@
 OpenLayers.Control.KeyboardDefaults = OpenLayers.Class(OpenLayers.Control, {
 
     /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
      * APIProperty: slideFactor
      * Pixels to slide by.
      */
@@ -53,7 +60,6 @@
     draw: function() {
         this.handler = new OpenLayers.Handler.Keyboard( this, { 
                                 "keydown": this.defaultKeyPress });
-        this.activate();
     },
     
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/LayerSwitcher.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/LayerSwitcher.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/LayerSwitcher.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /** 
@@ -22,11 +23,19 @@
 OpenLayers.Control.LayerSwitcher = 
   OpenLayers.Class(OpenLayers.Control, {
 
+    /**
+     * APIProperty: roundedCorner
+     * {Boolean} If true the Rico library is used for rounding the corners
+     *     of the layer switcher div, defaults to true.
+     */
+    roundedCorner: true,
+
     /**  
-     * Property: activeColor
-     * {String}
+     * APIProperty: roundedCornerColor
+     * {String} The color of the rounded corners, only applies if roundedCorner
+     *     is true, defaults to "darkblue".
      */
-    activeColor: "darkblue",
+    roundedCornerColor: "darkblue",
     
     /**  
      * Property: layerStates 
@@ -284,7 +293,7 @@
                 // create input element
                 var inputElem = document.createElement("input");
                 inputElem.id = this.id + "_input_" + layer.name;
-                inputElem.name = (baseLayer) ? "baseLayers" : layer.name;
+                inputElem.name = (baseLayer) ? this.id + "_baseLayers" : layer.name;
                 inputElem.type = (baseLayer) ? "radio" : "checkbox";
                 inputElem.value = layer.name;
                 inputElem.checked = checked;
@@ -305,6 +314,7 @@
                 
                 // create span
                 var labelSpan = document.createElement("span");
+                OpenLayers.Element.addClass(labelSpan, "labelSpan")
                 if (!baseLayer && !layer.inRange) {
                     labelSpan.style.color = "gray";
                 }
@@ -419,8 +429,9 @@
      */
     maximizeControl: function(e) {
 
-        //HACK HACK HACK - find a way to auto-size this layerswitcher
-        this.div.style.width = "20em";
+        // set the div's width and height to empty values, so
+        // the div dimensions can be controlled by CSS
+        this.div.style.width = "";
         this.div.style.height = "";
 
         this.showControls(false);
@@ -440,6 +451,10 @@
      */
     minimizeControl: function(e) {
 
+        // to minimize the control we set its div's width
+        // and height to 0px, we cannot just set "display"
+        // to "none" because it would hide the maximize
+        // div
         this.div.style.width = "0px";
         this.div.style.height = "0px";
 
@@ -473,19 +488,7 @@
     loadContents: function() {
 
         //configure main div
-        this.div.style.position = "absolute";
-        this.div.style.top = "25px";
-        this.div.style.right = "0px";
-        this.div.style.left = "";
-        this.div.style.fontFamily = "sans-serif";
-        this.div.style.fontWeight = "bold";
-        this.div.style.marginTop = "3px";
-        this.div.style.marginLeft = "3px";
-        this.div.style.marginBottom = "3px";
-        this.div.style.fontSize = "smaller";   
-        this.div.style.color = "white";   
-        this.div.style.backgroundColor = "transparent";
-    
+
         OpenLayers.Event.observe(this.div, "mouseup", 
             OpenLayers.Function.bindAsEventListener(this.mouseUp, this));
         OpenLayers.Event.observe(this.div, "click",
@@ -494,44 +497,24 @@
             OpenLayers.Function.bindAsEventListener(this.mouseDown, this));
         OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent);
 
-
         // layers list div        
         this.layersDiv = document.createElement("div");
         this.layersDiv.id = this.id + "_layersDiv";
-        this.layersDiv.style.paddingTop = "5px";
-        this.layersDiv.style.paddingLeft = "10px";
-        this.layersDiv.style.paddingBottom = "5px";
-        this.layersDiv.style.paddingRight = "75px";
-        this.layersDiv.style.backgroundColor = this.activeColor;        
+        OpenLayers.Element.addClass(this.layersDiv, "layersDiv");
 
-        // had to set width/height to get transparency in IE to work.
-        // thanks -- http://jszen.blogspot.com/2005/04/ie6-opacity-filter-caveat.html
-        //
-        this.layersDiv.style.width = "100%";
-        this.layersDiv.style.height = "100%";
-
-
         this.baseLbl = document.createElement("div");
         this.baseLbl.innerHTML = OpenLayers.i18n("baseLayer");
-        this.baseLbl.style.marginTop = "3px";
-        this.baseLbl.style.marginLeft = "3px";
-        this.baseLbl.style.marginBottom = "3px";
+        OpenLayers.Element.addClass(this.baseLbl, "baseLbl");
         
         this.baseLayersDiv = document.createElement("div");
-        this.baseLayersDiv.style.paddingLeft = "10px";
-        /*OpenLayers.Event.observe(this.baseLayersDiv, "click", 
-            OpenLayers.Function.bindAsEventListener(this.onLayerClick, this));
-        */
-                     
+        OpenLayers.Element.addClass(this.baseLayersDiv, "baseLayersDiv");
 
         this.dataLbl = document.createElement("div");
         this.dataLbl.innerHTML = OpenLayers.i18n("overlays");
-        this.dataLbl.style.marginTop = "3px";
-        this.dataLbl.style.marginLeft = "3px";
-        this.dataLbl.style.marginBottom = "3px";
+        OpenLayers.Element.addClass(this.dataLbl, "dataLbl");
         
         this.dataLayersDiv = document.createElement("div");
-        this.dataLayersDiv.style.paddingLeft = "10px";
+        OpenLayers.Element.addClass(this.dataLayersDiv, "dataLayersDiv");
 
         if (this.ascending) {
             this.layersDiv.appendChild(this.baseLbl);
@@ -547,13 +530,16 @@
  
         this.div.appendChild(this.layersDiv);
 
-        OpenLayers.Rico.Corner.round(this.div, {corners: "tl bl",
-                                        bgColor: "transparent",
-                                        color: this.activeColor,
-                                        blend: false});
+        if(this.roundedCorner) {
+            OpenLayers.Rico.Corner.round(this.div, {
+                corners: "tl bl",
+                bgColor: "transparent",
+                color: this.roundedCornerColor,
+                blend: false
+            });
+            OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
+        }
 
-        OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
-
         var imgLocation = OpenLayers.Util.getImagesLocation();
         var sz = new OpenLayers.Size(18,18);        
 
@@ -565,9 +551,7 @@
                                     sz, 
                                     img, 
                                     "absolute");
-        this.maximizeDiv.style.top = "5px";
-        this.maximizeDiv.style.right = "0px";
-        this.maximizeDiv.style.left = "";
+        OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv");
         this.maximizeDiv.style.display = "none";
         OpenLayers.Event.observe(this.maximizeDiv, "click", 
             OpenLayers.Function.bindAsEventListener(this.maximizeControl, this)
@@ -584,9 +568,7 @@
                                     sz, 
                                     img, 
                                     "absolute");
-        this.minimizeDiv.style.top = "5px";
-        this.minimizeDiv.style.right = "0px";
-        this.minimizeDiv.style.left = "";
+        OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv");
         this.minimizeDiv.style.display = "none";
         OpenLayers.Event.observe(this.minimizeDiv, "click", 
             OpenLayers.Function.bindAsEventListener(this.minimizeControl, this)

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Measure.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Measure.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Measure.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -32,7 +33,8 @@
      *      will receive an event with measure, units, order, and geometry
      *      properties.
      * measurepartial - Triggered when a new point is added to the
-     *      measurement sketch.  Listeners receive an event with measure,
+     *      measurement sketch or if the <immediate> property is true and the
+     *      measurement sketch is modified.  Listeners receive an event with measure,
      *      units, order, and geometry.
      */
     EVENT_TYPES: ['measure', 'measurepartial'],
@@ -92,7 +94,7 @@
      * {Number} Timeout id of trigger for measurepartial.
      */
     delayedTrigger: null,
-    
+
     /**
      * APIProperty: persist
      * {Boolean} Keep the temporary measurement sketch drawn after the
@@ -103,6 +105,14 @@
     persist: false,
 
     /**
+     * APIProperty: immediate
+     * {Boolean} Activates the immediate measurement so that the "measurepartial"
+     *     event is also fired once the measurement sketch is modified.
+     *     Default is false.
+     */
+    immediate : false,
+
+    /**
      * Constructor: OpenLayers.Control.Measure
      * 
      * Parameters:
@@ -116,10 +126,12 @@
             OpenLayers.Control.prototype.EVENT_TYPES
         );
         OpenLayers.Control.prototype.initialize.apply(this, [options]);
-        this.callbacks = OpenLayers.Util.extend(
-            {done: this.measureComplete, point: this.measurePartial},
-            this.callbacks
-        );
+        var callbacks = {done: this.measureComplete,
+            point: this.measurePartial};
+        if (this.immediate){
+            callbacks.modify = this.measureImmediate;
+        }
+        this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
 
         // let the handler options override, so old code that passes 'persist' 
         // directly to the handler does not need an update
@@ -130,13 +142,36 @@
     },
     
     /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        this.cancelDelay();
+        return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
+    },
+
+    /**
      * APIMethod: cancel
      * Stop the control from measuring.  If <persist> is true, the temporary
      *     sketch will be erased.
      */
     cancel: function() {
+        this.cancelDelay();
         this.handler.cancel();
     },
+
+    /**
+     * APIMethod: setImmediate
+     * Sets the <immediate> property. Changes the activity of immediate
+     * measurement.
+     */
+    setImmediate: function(immediate) {
+        this.immediate = immediate;
+        if (this.immediate){
+            this.callbacks.modify = this.measureImmediate;
+        } else {
+            delete this.callbacks.modify;
+        }
+    },
     
     /**
      * Method: updateHandler
@@ -164,9 +199,7 @@
      * geometry - {<OpenLayers.Geometry>}
      */
     measureComplete: function(geometry) {
-        if(this.delayedTrigger) {
-            window.clearTimeout(this.delayedTrigger);
-        }
+        this.cancelDelay();
         this.measure(geometry, "measure");
     },
     
@@ -179,15 +212,50 @@
      * geometry - {<OpenLayers.Geometry>} The sketch geometry.
      */
     measurePartial: function(point, geometry) {
-        this.delayedTrigger = window.setTimeout(
-            OpenLayers.Function.bind(function() {
-                this.measure(geometry, "measurepartial");
-            }, this),
-            this.partialDelay
-        );
+        this.cancelDelay();
+        geometry = geometry.clone();
+        // when we're wating for a dblclick, we have to trigger measurepartial
+        // after some delay to deal with reflow issues in IE
+        if (this.handler.freehandMode(this.handler.evt)) {
+            // no dblclick in freehand mode
+            this.measure(geometry, "measurepartial");
+        } else {
+            this.delayedTrigger = window.setTimeout(
+                OpenLayers.Function.bind(function() {
+                    this.delayedTrigger = null;
+                    this.measure(geometry, "measurepartial");
+                }, this),
+                this.partialDelay
+            );
+        }
     },
 
     /**
+     * Method: measureImmediate
+     * Called each time the measurement sketch is modified.
+     * 
+     * Parameters: point - {<OpenLayers.Geometry.Point>} The point at the
+     * mouseposition. feature - {<OpenLayers.Feature.Vector>} The sketch feature.
+     */
+    measureImmediate : function(point, feature) {
+        if (this.delayedTrigger === null &&
+                                !this.handler.freehandMode(this.handler.evt)) {
+            this.measure(feature.geometry, "measurepartial");
+        }
+    },
+
+    /**
+     * Method: cancelDelay
+     * Cancels the delay measurement that measurePartial began.
+     */
+    cancelDelay: function() {
+        if (this.delayedTrigger !== null) {
+            window.clearTimeout(this.delayedTrigger);
+            this.delayedTrigger = null;
+        }
+    },
+
+    /**
      * Method: measure
      *
      * Parameters:

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ModifyFeature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ModifyFeature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ModifyFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,8 +1,8 @@
-/* Copyright (c) 2006 MetaCarta, Inc., published under the Clear BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt 
- * for the full text of the license. */
+/* 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/Control/DragFeature.js
  * @requires OpenLayers/Control/SelectFeature.js
@@ -43,6 +43,17 @@
      *      Default is true.
      */
     toggle: true,
+    
+    /**
+     * APIProperty: standalone
+     * {Boolean} Set to true to create a control without SelectFeature
+     *     capabilities. Default is false.  If standalone is true, to modify
+     *     a feature, call the <selectFeature> method with the target feature.
+     *     Note that you must call the <unselectFeature> method to finish
+     *     feature modification in standalone mode (before starting to modify
+     *     another feature).
+     */
+    standalone: false,
 
     /**
      * Property: layer
@@ -107,7 +118,7 @@
      * APIProperty: mode
      * {Integer} Bitfields specifying the modification mode. Defaults to
      *      OpenLayers.Control.ModifyFeature.RESHAPE. To set the mode to a
-     *      combination of options, use the | operator. or example, to allow
+     *      combination of options, use the | operator. For example, to allow
      *      the control to both resize and rotate features, use the following
      *      syntax
      * (code)
@@ -207,9 +218,11 @@
             onUnselect: this.unselectFeature,
             scope: this
         };
-        this.selectControl = new OpenLayers.Control.SelectFeature(
-            layer, selectOptions
-        );
+        if(this.standalone === false) {
+            this.selectControl = new OpenLayers.Control.SelectFeature(
+                layer, selectOptions
+            );
+        }
 
         // configure the drag control
         var dragOptions = {
@@ -223,6 +236,22 @@
             },
             onComplete: function(feature) {
                 control.dragComplete.apply(control, [feature]);
+            },
+            featureCallbacks: {
+                over: function(feature) {
+                    /**
+                     * In normal mode, the feature handler is set up to allow
+                     * dragging of all points.  In standalone mode, we only
+                     * want to allow dragging of sketch vertices and virtual
+                     * vertices - or, in the case of a modifiable point, the
+                     * point itself.
+                     */
+                    if(control.standalone !== true || feature._sketch ||
+                       control.feature === feature) {
+                        control.dragControl.overFeature.apply(
+                            control.dragControl, [feature]);
+                    }
+                }
             }
         };
         this.dragControl = new OpenLayers.Control.DragFeature(
@@ -244,7 +273,7 @@
      */
     destroy: function() {
         this.layer = null;
-        this.selectControl.destroy();
+        this.standalone || this.selectControl.destroy();
         this.dragControl.destroy();
         OpenLayers.Control.prototype.destroy.apply(this, []);
     },
@@ -257,7 +286,7 @@
      * {Boolean} Successfully activated the control.
      */
     activate: function() {
-        return (this.selectControl.activate() &&
+        return ((this.standalone || this.selectControl.activate()) &&
                 this.handlers.keyboard.activate() &&
                 OpenLayers.Control.prototype.activate.apply(this, arguments));
     },
@@ -277,11 +306,19 @@
             this.layer.removeFeatures(this.virtualVertices, {silent: true});
             this.vertices = [];
             this.dragControl.deactivate();
-            if(this.feature && this.feature.geometry && this.feature.layer) {
-                this.selectControl.unselect.apply(this.selectControl,
-                                                  [this.feature]);
+            var feature = this.feature;
+            var valid = feature && feature.geometry && feature.layer;
+            if(this.standalone === false) {
+                if(valid) {
+                    this.selectControl.unselect.apply(this.selectControl,
+                                                      [feature]);
+                }
+                this.selectControl.deactivate();
+            } else {
+                if(valid) {
+                    this.unselectFeature(feature);
+                }
             }
-            this.selectControl.deactivate();
             this.handlers.keyboard.deactivate();
             deactivated = true;
         }
@@ -364,7 +401,7 @@
         // only change behavior if the feature is not in the vertices array
         if(feature != this.feature && !feature.geometry.parent &&
            feature != this.dragHandle && feature != this.radiusHandle) {
-            if(this.feature) {
+            if(this.standalone === false && this.feature) {
                 // unselect the currently selected feature
                 this.selectControl.clickFeature.apply(this.selectControl,
                                                       [this.feature]);
@@ -374,8 +411,8 @@
                OpenLayers.Util.indexOf(this.geometryTypes,
                                        feature.geometry.CLASS_NAME) != -1) {
                 // select the point
-                this.selectControl.clickFeature.apply(this.selectControl,
-                                                      [feature]);
+                this.standalone || this.selectControl.clickFeature.apply(
+                                            this.selectControl, [feature]);
                 /**
                  * TBD: These lines improve workflow by letting the user
                  *     immediately start dragging after the mouse down.
@@ -452,7 +489,8 @@
                 this.layer.destroyFeatures(this.virtualVertices, {silent: true});
                 this.virtualVertices = [];
             }
-            this.layer.drawFeature(this.feature, this.selectControl.renderIntent);
+            this.layer.drawFeature(this.feature, this.standalone ? undefined :
+                                            this.selectControl.renderIntent);
         }
         // keep the vertex on top so it gets the mouseout after dragging
         // this should be removed in favor of an option to draw under or
@@ -558,7 +596,8 @@
                vertex.geometry.parent) {
                 // remove the vertex
                 vertex.geometry.parent.removeComponent(vertex.geometry);
-                this.layer.drawFeature(this.feature,
+                this.layer.drawFeature(this.feature, this.standalone ?
+                                       undefined :
                                        this.selectControl.renderIntent);
                 this.resetVertices();
                 this.setFeatureState();
@@ -708,7 +747,7 @@
      * map - {<OpenLayers.Map>} The control's map.
      */
     setMap: function(map) {
-        this.selectControl.setMap(map);
+        this.standalone || this.selectControl.setMap(map);
         this.dragControl.setMap(map);
         OpenLayers.Control.prototype.setMap.apply(this, arguments);
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseDefaults.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseDefaults.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseDefaults.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -166,7 +167,7 @@
             this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
             this.map.viewPortDiv.appendChild(this.zoomBox);
         }
-        document.onselectstart=function() { return false; };
+        document.onselectstart = OpenLayers.Function.False;
         OpenLayers.Event.stop(evt);
     },
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/MousePosition.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/MousePosition.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/MousePosition.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -17,6 +18,13 @@
  */
 OpenLayers.Control.MousePosition = OpenLayers.Class(OpenLayers.Control, {
     
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
     /** 
      * Property: element
      * {DOMElement} 
@@ -52,6 +60,13 @@
      * {Integer} 
      */
     granularity: 10,
+
+    /**
+     * APIProperty: emptyString 
+     * {String} Set this to some value to set when the mouse is outside the
+     *     map.
+     */
+    emptyString: null,
     
     /** 
      * Property: lastXy
@@ -80,13 +95,39 @@
      * Method: destroy
      */
      destroy: function() {
-         if (this.map) {
-             this.map.events.unregister('mousemove', this, this.redraw);
-         }
+         this.deactivate();
          OpenLayers.Control.prototype.destroy.apply(this, arguments);
      },
 
     /**
+     * APIMethod: activate
+     */
+    activate: function() {
+        if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.map.events.register('mousemove', this, this.redraw);
+            this.map.events.register('mouseout', this, this.reset);
+            this.redraw();
+            return true;
+        } else {
+            return false;
+        }
+    },
+    
+    /**
+     * APIMethod: deactivate
+     */
+    deactivate: function() {
+        if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.map.events.unregister('mousemove', this, this.redraw);
+            this.map.events.unregister('mouseout', this, this.reset);
+            this.element.innerHTML = "";
+            return true;
+        } else {
+            return false;
+        }
+    },
+
+    /**
      * Method: draw
      * {DOMElement}
      */    
@@ -99,7 +140,6 @@
             this.element = this.div;
         }
         
-        this.redraw();
         return this.div;
     },
    
@@ -111,7 +151,8 @@
         var lonLat;
 
         if (evt == null) {
-            lonLat = new OpenLayers.LonLat(0, 0);
+            this.reset();
+            return;
         } else {
             if (this.lastXy == null ||
                 Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
@@ -142,6 +183,15 @@
     },
 
     /**
+     * Method: reset
+     */
+    reset: function(evt) {
+        if (this.emptyString != null) {
+            this.element.innerHTML = this.emptyString;
+        }
+    },
+
+    /**
      * Method: formatOutput
      * Override to provide custom display output
      *
@@ -157,15 +207,7 @@
             lonLat.lat.toFixed(digits) +
             this.suffix;
         return newHtml;
-     },
+    },
 
-    /** 
-     * Method: setMap
-     */
-    setMap: function() {
-        OpenLayers.Control.prototype.setMap.apply(this, arguments);
-        this.map.events.register( 'mousemove', this, this.redraw);
-    },     
-
     CLASS_NAME: "OpenLayers.Control.MousePosition"
 });

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseToolbar.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseToolbar.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseToolbar.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -254,7 +255,7 @@
                 this.map.div.style.cursor = "move";
                 break;
         }
-        document.onselectstart = function() { return false; };
+        document.onselectstart = OpenLayers.Function.False;
         OpenLayers.Event.stop(evt);
     },
 


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Control/MouseToolbar.js
___________________________________________________________________
Deleted: svn:mime-type
   - text/cpp

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/NavToolbar.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/NavToolbar.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/NavToolbar.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Control/NavToolbar.js
___________________________________________________________________
Deleted: svn:mime-type
   - text/plain

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Navigation.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Navigation.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Navigation.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -36,6 +37,13 @@
      */
     dragPanOptions: null,
 
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} Allow panning of the map by dragging outside map viewport.
+     *     Default is false.
+     */
+    documentDrag: false,
+
     /** 
      * Property: zoomBox
      * {<OpenLayers.Control.ZoomBox>}
@@ -43,10 +51,23 @@
     zoomBox: null,
 
     /**
+     * APIProperty: zoomBoxEnabled
+     * {Boolean} Whether the user can draw a box to zoom
+     */
+    zoomBoxEnabled: true, 
+
+    /**
      * APIProperty: zoomWheelEnabled
      * {Boolean} Whether the mousewheel should zoom the map
      */
-    zoomWheelEnabled: true, 
+    zoomWheelEnabled: true,
+    
+    /**
+     * Property: mouseWheelOptions
+     * {Object} Options passed to the MouseWheel control (only useful if
+     *     <zoomWheelEnabled> is set to true)
+     */
+    mouseWheelOptions: null,
 
     /**
      * APIProperty: handleRightClicks
@@ -66,6 +87,13 @@
     zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT,
     
     /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
+    /**
      * Constructor: OpenLayers.Control.Navigation
      * Create a new navigation control
      * 
@@ -108,7 +136,9 @@
             this.handlers.wheel.activate();
         }    
         this.handlers.click.activate();
-        this.zoomBox.activate();
+        if (this.zoomBoxEnabled) {
+            this.zoomBox.activate();
+        }
         return OpenLayers.Control.prototype.activate.apply(this,arguments);
     },
 
@@ -129,7 +159,7 @@
     draw: function() {
         // disable right mouse context menu for support of right click events
         if (this.handleRightClicks) {
-            this.map.viewPortDiv.oncontextmenu = function () { return false;};
+            this.map.viewPortDiv.oncontextmenu = OpenLayers.Function.False;
         }
 
         var clickCallbacks = { 
@@ -144,7 +174,10 @@
             this, clickCallbacks, clickOptions
         );
         this.dragPan = new OpenLayers.Control.DragPan(
-            OpenLayers.Util.extend({map: this.map}, this.dragPanOptions)
+            OpenLayers.Util.extend({
+                map: this.map,
+                documentDrag: this.documentDrag
+            }, this.dragPanOptions)
         );
         this.zoomBox = new OpenLayers.Control.ZoomBox(
                     {map: this.map, keyMask: this.zoomBoxKeyMask});
@@ -152,8 +185,8 @@
         this.zoomBox.draw();
         this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
                                     this, {"up"  : this.wheelUp,
-                                           "down": this.wheelDown} );
-        this.activate();
+                                           "down": this.wheelDown},
+                                    this.mouseWheelOptions );
     },
 
     /**
@@ -186,8 +219,11 @@
      * deltaZ - {Integer}
      */
     wheelChange: function(evt, deltaZ) {
-        var newZoom = this.map.getZoom() + deltaZ;
-        if (!this.map.isValidZoomLevel(newZoom)) {
+        var currentZoom = this.map.getZoom();
+        var newZoom = this.map.getZoom() + Math.round(deltaZ);
+        newZoom = Math.max(newZoom, 0);
+        newZoom = Math.min(newZoom, this.map.getNumZoomLevels());
+        if (newZoom === currentZoom) {
             return;
         }
         var size    = this.map.getSize();
@@ -207,9 +243,10 @@
      * 
      * Parameters:
      * evt - {Event}
+     * delta - {Integer}
      */
-    wheelUp: function(evt) {
-        this.wheelChange(evt, 1);
+    wheelUp: function(evt, delta) {
+        this.wheelChange(evt, delta || 1);
     },
 
     /** 
@@ -218,12 +255,31 @@
      * 
      * Parameters:
      * evt - {Event}
+     * delta - {Integer}
      */
-    wheelDown: function(evt) {
-        this.wheelChange(evt, -1);
+    wheelDown: function(evt, delta) {
+        this.wheelChange(evt, delta || -1);
     },
     
     /**
+     * Method: disableZoomBox
+     */
+    disableZoomBox : function() {
+        this.zoomBoxEnabled = false;
+        this.zoomBox.deactivate();       
+    },
+    
+    /**
+     * Method: enableZoomBox
+     */
+    enableZoomBox : function() {
+        this.zoomBoxEnabled = true;
+        if (this.active) {
+            this.zoomBox.activate();
+        }    
+    },
+    
+    /**
      * Method: disableZoomWheel
      */
     

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/NavigationHistory.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/NavigationHistory.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/NavigationHistory.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -67,11 +68,11 @@
     limit: 50,
 
     /**
-     * Property: activateOnDraw
-     * {Boolean} Activate the control when it is first added to the map.
-     *     Default is true.
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
      */
-    activateOnDraw: true,
+    autoActivate: true,
 
     /**
      * Property: clearOnDeactivate
@@ -126,16 +127,9 @@
         OpenLayers.Control.prototype.initialize.apply(this, [options]);
         
         this.registry = OpenLayers.Util.extend({
-            "moveend": function() {
-                return {
-                    center: this.map.getCenter(),
-                    resolution: this.map.getResolution()                
-                };
-            }
+            "moveend": this.getState
         }, this.registry);
         
-        this.clear();
-
         var previousOptions = {
             trigger: OpenLayers.Function.bind(this.previousTrigger, this),
             displayClass: this.displayClass + " " + this.displayClass + "Previous"
@@ -150,6 +144,7 @@
         OpenLayers.Util.extend(nextOptions, this.nextOptions);
         this.next = new OpenLayers.Control.Button(nextOptions);
 
+        this.clear();
     },
     
     /**
@@ -224,9 +219,6 @@
         OpenLayers.Control.prototype.draw.apply(this, arguments);
         this.next.draw();
         this.previous.draw();
-        if(this.activateOnDraw) {
-            this.activate();
-        }
     },
     
     /**
@@ -288,10 +280,29 @@
      */
     clear: function() {
         this.previousStack = [];
+        this.previous.deactivate();
         this.nextStack = [];
+        this.next.deactivate();
     },
 
     /**
+     * Method: getState
+     * Get the current state and return it.
+     *
+     * Returns:
+     * {Object} An object representing the current state.
+     */
+    getState: function() {
+        return {
+            center: this.map.getCenter(),
+            resolution: this.map.getResolution(),
+            projection: this.map.getProjectionObject(),
+            units: this.map.getProjectionObject().getUnits() || 
+                this.map.units || this.map.baseLayer.units
+        };
+    },
+
+    /**
      * Method: restore
      * Update the state with the given object.
      *
@@ -299,8 +310,21 @@
      * state - {Object} An object representing the state to restore.
      */
     restore: function(state) {
-        var zoom = this.map.getZoomForResolution(state.resolution);
-        this.map.setCenter(state.center, zoom);
+        var center, zoom;
+        if (this.map.getProjectionObject() == state.projection) { 
+            zoom = this.map.getZoomForResolution(state.resolution);
+            center = state.center;
+        } else {
+            center = state.center.clone();
+            center.transform(state.projection, this.map.getProjectionObject());
+            var sourceUnits = state.units;
+            var targetUnits = this.map.getProjectionObject().getUnits() || 
+                this.map.units || this.map.baseLayer.units;
+            var resolutionFactor = sourceUnits && targetUnits ? 
+                OpenLayers.INCHES_PER_UNIT[sourceUnits] / OpenLayers.INCHES_PER_UNIT[targetUnits] : 1;
+            zoom = this.map.getZoomForResolution(resolutionFactor*state.resolution); 
+        }
+        this.map.setCenter(center, zoom);
     },
     
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/OverviewMap.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/OverviewMap.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/OverviewMap.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /** 
@@ -121,6 +122,12 @@
     resolutionFactor: 1,
 
     /**
+     * APIProperty: maximized
+     * {Boolean} Start as maximized (visible). Defaults to false.
+     */
+    maximized: false,
+
+    /**
      * Constructor: OpenLayers.Control.OverviewMap
      * Create a new overview map
      *
@@ -143,15 +150,25 @@
         if (!this.mapDiv) { // we've already been destroyed
             return;
         }
-        this.handlers.click.destroy();
+        if (this.handlers.click) {
+            this.handlers.click.destroy();
+        }
+        if (this.handlers.drag) {
+            this.handlers.drag.destroy();
+        }
 
-        this.mapDiv.removeChild(this.extentRectangle);
+        this.ovmap && this.ovmap.viewPortDiv.removeChild(this.extentRectangle);
         this.extentRectangle = null;
-        this.rectEvents.destroy();
-        this.rectEvents = null;
 
-        this.ovmap.destroy();
-        this.ovmap = null;
+        if (this.rectEvents) {
+            this.rectEvents.destroy();
+            this.rectEvents = null;
+        }
+
+        if (this.ovmap) {
+            this.ovmap.destroy();
+            this.ovmap = null;
+        }
         
         this.element.removeChild(this.mapDiv);
         this.mapDiv = null;
@@ -170,7 +187,7 @@
             this.div.removeChild(this.minimizeDiv);
             this.minimizeDiv = null;
         }
-        
+
         this.map.events.un({
             "moveend": this.update,
             "changebaselayer": this.baseLayerDraw,
@@ -212,7 +229,6 @@
         this.extentRectangle.style.position = 'absolute';
         this.extentRectangle.style.zIndex = 1000;  //HACK
         this.extentRectangle.className = this.displayClass+'ExtentRectangle';
-        this.mapDiv.appendChild(this.extentRectangle);
 
         this.element.appendChild(this.mapDiv);  
 
@@ -278,7 +294,10 @@
         }
         
         this.map.events.register('moveend', this, this.update);
-
+        
+        if (this.maximized) {
+            this.maximizeControl();
+        }
         return this.div;
     },
     
@@ -470,6 +489,7 @@
                         {controls: [], maxResolution: 'auto', 
                          fallThrough: false}, this.mapOptions);
         this.ovmap = new OpenLayers.Map(this.mapDiv, options);
+        this.ovmap.viewPortDiv.appendChild(this.extentRectangle);
         
         // prevent ovmap from being destroyed when the page unloads, because
         // the OverviewMap control has to do this (and does it).

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Pan.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Pan.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Pan.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -19,7 +20,7 @@
     /** 
      * APIProperty: slideFactor
      * {Integer} Number of pixels by which we'll pan the map in any direction 
-     *     on clicking the arrow buttons. 
+     *     on clicking the arrow buttons, defaults to 50.
      */
     slideFactor: 50,
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/PanPanel.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/PanPanel.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/PanPanel.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Control/Panel.js
  * @requires OpenLayers/Control/Pan.js
@@ -25,6 +30,13 @@
  */
 OpenLayers.Control.PanPanel = OpenLayers.Class(OpenLayers.Control.Panel, {
 
+    /** 
+     * APIProperty: slideFactor
+     * {Integer} Number of pixels by which we'll pan the map in any direction 
+     *     on clicking the arrow buttons, defaults to 50.
+     */
+    slideFactor: 50,
+
     /**
      * Constructor: OpenLayers.Control.PanPanel 
      * Add the four directional pan buttons.
@@ -36,10 +48,14 @@
     initialize: function(options) {
         OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
         this.addControls([
-            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH),
-            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH),
-            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST),
-            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST)
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH,
+                                       {slideFactor: this.slideFactor}),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH,
+                                       {slideFactor: this.slideFactor}),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST,
+                                       {slideFactor: this.slideFactor}),
+            new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST,
+                                       {slideFactor: this.slideFactor})
         ]);
     },
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoom.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoom.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoom.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -163,6 +164,7 @@
     _removeButton: function(btn) {
         OpenLayers.Event.stopObservingElement(btn);
         btn.map = null;
+        btn.getSlideFactor = null;
         this.div.removeChild(btn);
         OpenLayers.Util.removeItem(this.buttons, btn);
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoomBar.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoomBar.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/PanZoomBar.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -41,10 +42,10 @@
     sliderEvents: null,
 
     /** 
-     * Property: zoomBarDiv
+     * Property: zoombarDiv
      * {DOMElement}
      */
-    zoomBarDiv: null,
+    zoombarDiv: null,
 
     /** 
      * Property: divEvents
@@ -59,6 +60,25 @@
     zoomWorldIcon: false,
 
     /**
+     * APIProperty: forceFixedZoomLevel
+     * {Boolean} Force a fixed zoom level even though the map has 
+     *     fractionalZoom
+     */
+    forceFixedZoomLevel: false,
+
+    /**
+     * Property: mouseDragStart
+     * {<OpenLayers.Pixel>}
+     */
+    mouseDragStart: null,
+
+    /**
+     * Property: zoomStart
+     * {<OpenLayers.Pixel>}
+     */
+    zoomStart: null,
+
+    /**
      * Constructor: OpenLayers.Control.PanZoomBar
      */ 
     initialize: function() {
@@ -78,6 +98,9 @@
         });
 
         OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
+
+        delete this.mouseDragStart;
+        delete this.zoomStart;
     },
     
     /**
@@ -263,10 +286,8 @@
         if (!OpenLayers.Event.isLeftClick(evt)) {
             return;
         }
-        var y = evt.xy.y;
-        var top = OpenLayers.Util.pagePosition(evt.object)[1];
-        var levels = (y - top)/this.zoomStopHeight;
-        if(!this.map.fractionalZoom) {
+        var levels = evt.xy.y / this.zoomStopHeight;
+        if(this.forceFixedZoomLevel || !this.map.fractionalZoom) {
             levels = Math.floor(levels);
         }    
         var zoom = (this.map.getNumZoomLevels() - 1) - levels; 
@@ -335,7 +356,7 @@
         if (!OpenLayers.Event.isLeftClick(evt)) {
             return;
         }
-        if (this.zoomStart) {
+        if (this.mouseDragStart) {
             this.div.style.cursor="";
             this.map.events.un({
                 "mouseup": this.passEventToSlider,
@@ -344,7 +365,7 @@
             });
             var deltaY = this.zoomStart.y - evt.xy.y;
             var zoomLevel = this.map.zoom;
-            if (this.map.fractionalZoom) {
+            if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
                 zoomLevel += deltaY/this.zoomStopHeight;
                 zoomLevel = Math.min(Math.max(zoomLevel, 0), 
                                      this.map.getNumZoomLevels() - 1);
@@ -352,8 +373,8 @@
                 zoomLevel += Math.round(deltaY/this.zoomStopHeight);
             }
             this.map.zoomTo(zoomLevel);
-            this.moveZoomBar();
             this.mouseDragStart = null;
+            this.zoomStart = null;
             OpenLayers.Event.stop(evt);
         }
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Panel.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Panel.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Panel.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -21,17 +22,65 @@
      */
     controls: null,    
     
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     true.
+     */
+    autoActivate: true,
+
     /** 
      * APIProperty: defaultControl
      * {<OpenLayers.Control>} The control which is activated when the control is
      * activated (turned on), which also happens at instantiation.
+     * If <saveState> is true, <defaultControl> will be nullified after the
+     * first activation of the panel.
      */
-    defaultControl: null, 
+    defaultControl: null,
+    
+    /**
+     * APIProperty: saveState
+     * {Boolean} If set to true, the active state of this panel's controls will
+     * be stored on panel deactivation, and restored on reactivation. Default
+     * is false.
+     */
+    saveState: false,
+      
+    /**
+     * Property: activeState
+     * {Object} stores the active state of this panel's controls.
+     */
+    activeState: null,
 
     /**
      * Constructor: OpenLayers.Control.Panel
      * Create a new control panel.
-     * 
+     *
+     * Each control in the panel is represented by an icon. When clicking 
+     *     on an icon, the <activateControl> method is called.
+     *
+     * Specific properties for controls on a panel:
+     * type - {Number} One of <OpenLayers.Control.TYPE_TOOL>,
+     *     <OpenLayers.Control.TYPE_TOGGLE>, <OpenLayers.Control.TYPE_BUTTON>.
+     *     If not provided, <OpenLayers.Control.TYPE_TOOL> is assumed.
+     * title - {string} Text displayed when mouse is over the icon that 
+     *     represents the control.     
+     *
+     * The <OpenLayers.Control.type> of a control determines the behavior when
+     * clicking its icon:
+     * <OpenLayers.Control.TYPE_TOOL> - The control is activated and other
+     *     controls of this type in the same panel are deactivated. This is
+     *     the default type.
+     * <OpenLayers.Control.TYPE_TOGGLE> - The active state of the control is
+     *     toggled.
+     * <OpenLayers.Control.TYPE_BUTTON> - The
+     *     <OpenLayers.Control.Button.trigger> method of the control is called,
+     *     but its active state is not changed.
+     *
+     * If a control is <OpenLayers.Control.active>, it will be drawn with the
+     * olControl[Name]ItemActive class, otherwise with the
+     * olControl[Name]ItemInactive class.
+     *
      * Parameters:
      * options - {Object} An optional object whose properties will be used
      *     to extend the control.
@@ -39,6 +88,7 @@
     initialize: function(options) {
         OpenLayers.Control.prototype.initialize.apply(this, [options]);
         this.controls = [];
+        this.activeState = {};
     },
 
     /**
@@ -56,7 +106,8 @@
             }
             OpenLayers.Event.stopObservingElement(this.controls[i].panel_div);
             this.controls[i].panel_div = null;
-        }    
+        }
+        this.activeState = null;
     },
 
     /**
@@ -64,11 +115,17 @@
      */
     activate: function() {
         if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
-            for(var i=0, len=this.controls.length; i<len; i++) {
-                if (this.controls[i] == this.defaultControl) {
-                    this.controls[i].activate();
+            var control;
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                control = this.controls[i];
+                if (control === this.defaultControl ||
+                            (this.saveState && this.activeState[control.id])) {
+                    control.activate();
                 }
             }    
+            if (this.saveState === true) {
+                this.defaultControl = null;
+            }
             this.redraw();
             return true;
         } else {
@@ -81,9 +138,12 @@
      */
     deactivate: function() {
         if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
-            for(var i=0, len=this.controls.length; i<len; i++) {
-                this.controls[i].deactivate();
+            var control;
+            for (var i=0, len=this.controls.length; i<len; i++) {
+                control = this.controls[i];
+                this.activeState[control.id] = control.deactivate();
             }    
+            this.redraw();
             return true;
         } else {
             return false;
@@ -98,16 +158,7 @@
      */    
     draw: function() {
         OpenLayers.Control.prototype.draw.apply(this, arguments);
-        for (var i=0, len=this.controls.length; i<len; i++) {
-            this.map.addControl(this.controls[i]);
-            this.controls[i].deactivate();
-            this.controls[i].events.on({
-                "activate": this.redraw,
-                "deactivate": this.redraw,
-                scope: this
-            });
-        }
-        this.activate();
+        this.addControlsToMap(this.controls);
         return this.div;
     },
 
@@ -115,6 +166,9 @@
      * Method: redraw
      */
     redraw: function() {
+        for (var l=this.div.childNodes.length, i=l-1; i>=0; i--) {
+            this.div.removeChild(this.div.childNodes[i]);
+        }
         this.div.innerHTML = "";
         if (this.active) {
             for (var i=0, len=this.controls.length; i<len; i++) {
@@ -131,7 +185,9 @@
 
     /**
      * APIMethod: activateControl
-     * 
+     * This method is called when the user click on the icon representing a 
+     *     control in the panel.
+     *
      * Parameters:
      * control - {<OpenLayers.Control>}
      */
@@ -148,14 +204,14 @@
             } else {
                 control.activate();
             }
-            this.redraw();
             return;
         }
+        var c;
         for (var i=0, len=this.controls.length; i<len; i++) {
-            if (this.controls[i] != control) {
-                if (this.controls[i].type != OpenLayers.Control.TYPE_TOGGLE) {
-                    this.controls[i].deactivate();
-                }
+            c = this.controls[i];
+            if (c != control &&
+               (c.type === OpenLayers.Control.TYPE_TOOL || c.type == null)) {
+                c.deactivate();
             }
         }
         control.activate();
@@ -168,7 +224,7 @@
      * Control Panel.
      *
      * Parameters:
-     * controls - {<OpenLayers.Control>} 
+     * controls - {<OpenLayers.Control>} Controls to add in the panel.
      */    
     addControls: function(controls) {
         if (!(controls instanceof Array)) {
@@ -183,32 +239,52 @@
         // since they need to pass through.
         for (var i=0, len=controls.length; i<len; i++) {
             var element = document.createElement("div");
-            var textNode = document.createTextNode(" ");
             controls[i].panel_div = element;
             if (controls[i].title != "") {
                 controls[i].panel_div.title = controls[i].title;
             }
             OpenLayers.Event.observe(controls[i].panel_div, "click", 
                 OpenLayers.Function.bind(this.onClick, this, controls[i]));
+            OpenLayers.Event.observe(controls[i].panel_div, "dblclick", 
+                OpenLayers.Function.bind(this.onDoubleClick, this, controls[i]));
             OpenLayers.Event.observe(controls[i].panel_div, "mousedown", 
                 OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));
         }    
 
         if (this.map) { // map.addControl() has already been called on the panel
-            for (var i=0, len=controls.length; i<len; i++) {
-                this.map.addControl(controls[i]);
-                controls[i].deactivate();
-                controls[i].events.on({
-                    "activate": this.redraw,
-                    "deactivate": this.redraw,
-                    scope: this
-                });
-            }
+            this.addControlsToMap(controls);
             this.redraw();
         }
     },
    
     /**
+     * Method: addControlsToMap
+     * Only for internal use in draw() and addControls() methods.
+     *
+     * Parameters:
+     * controls - {Array(<OpenLayers.Control>)} Controls to add into map.
+     */         
+    addControlsToMap: function (controls) {
+        var control;
+        for (var i=0, len=controls.length; i<len; i++) {
+            control = controls[i];
+            if (control.autoActivate === true) {
+                control.autoActivate = false;
+                this.map.addControl(control);
+                control.autoActivate = true;
+            } else {
+                this.map.addControl(control);
+                control.deactivate();
+            }
+            control.events.on({
+                "activate": this.redraw,
+                "deactivate": this.redraw,
+                scope: this
+            });
+        }  
+    },
+
+    /**
      * Method: onClick
      */
     onClick: function (ctrl, evt) {
@@ -217,6 +293,13 @@
     },
 
     /**
+     * Method: onDoubleClick
+     */
+    onDoubleClick: function(ctrl, evt) {
+        OpenLayers.Event.stop(evt ? evt : window.event);
+    },
+
+    /**
      * APIMethod: getControlsBy
      * Get a list of controls with properties matching the given criteria.
      *

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Permalink.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Permalink.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Permalink.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -121,7 +122,6 @@
         OpenLayers.Control.prototype.draw.apply(this, arguments);
           
         if (!this.element) {
-            this.div.className = this.displayClass;
             this.element = document.createElement("a");
             this.element.innerHTML = OpenLayers.i18n("permalink");
             this.element.href="";

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Control/SLDSelect.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Control/SLDSelect.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/SLDSelect.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/SLDSelect.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,571 @@
+/* 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/Control.js
+ * @requires OpenLayers/Layer/WMS.js
+ * @requires OpenLayers/Handler/RegularPolygon.js
+ * @requires OpenLayers/Handler/Polygon.js
+ * @requires OpenLayers/Handler/Path.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Control.SLDSelect
+ * Perform selections on WMS layers using Styled Layer Descriptor (SLD)
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.SLDSelect = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     * {Array(String)} Supported application event types.  Register a listener
+     *     for a particular event with the following syntax:
+     * (code)
+     * control.events.register(type, obj, listener);
+     * (end)
+     *
+     * Listeners will be called with a reference to an event object.  The
+     *     properties of this event depends on exactly what happened.
+     *
+     * Supported control event types (in addition to those from 
+     * <OpenLayers.Control>):
+     * selected - Triggered when a selection occurs.  Listeners receive an 
+     *     event with *filters* and *layer* properties.  Filters will be an 
+     *     array of OpenLayers.Filter objects created in order to perform 
+     *     the particular selection.
+     */
+    EVENT_TYPES: ["selected"],
+
+    /**
+     * APIProperty: clearOnDeactivate
+     * {Boolean} Should the selection be cleared when the control is 
+     *     deactivated. Default value is false.
+     */
+    clearOnDeactivate: false,
+
+    /**
+     * APIProperty: layers
+     * {Array(<OpenLayers.Layer.WMS>)} The WMS layers this control will work 
+     *     on.
+     */
+    layers: null,
+
+    /**
+     * Property: callbacks
+     * {Object} The functions that are sent to the handler for callback
+     */
+    callbacks: null,
+
+    /**
+     * APIProperty: selectionSymbolizer
+     * {Object} Determines the styling of the selected objects. Default is
+     *     a selection in red.
+     */
+    selectionSymbolizer: {
+        'Polygon': {fillColor: '#FF0000', stroke: false},
+        'Line': {strokeColor: '#FF0000', strokeWidth: 2},
+        'Point': {graphicName: 'square', fillColor: '#FF0000', pointRadius: 5}
+    },
+
+    /**
+     * APIProperty: layerOptions
+     * {Object} The options to apply to the selection layer, by default the
+     *     selection layer will be kept out of the layer switcher.
+     */
+    layerOptions: null,
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Used to set non-default properties on the control's handler
+     */
+    handlerOptions: null,
+
+    /**
+     * APIProperty: sketchStyle
+     * {<OpenLayers.Style>|Object} Style or symbolizer to use for the sketch
+     * handler. The recommended way of styling the sketch layer, however, is
+     * to configure an <OpenLayers.StyleMap> in the layerOptions of the
+     * <handlerOptions>:
+     * 
+     * (code)
+     * new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Path, {
+     *     handlerOptions: {
+     *         layerOptions: {
+     *             styleMap: new OpenLayers.StyleMap({
+     *                 "default": {strokeColor: "yellow"}
+     *             });
+     *         }
+     *     }
+     * });
+     * (end)
+     */
+    sketchStyle: null,
+
+    /**
+     * APIProperty: wfsCache
+     * {Object} Cache to use for storing parsed results from
+     *     <OpenLayers.Format.WFSDescribeFeatureType.read>. If not provided,
+     *     these will be cached on the prototype.
+     */
+    wfsCache: {},
+
+    /**
+     * APIProperty: layerCache
+     * {Object} Cache to use for storing references to the selection layers.
+     *     Normally each source layer will have exactly 1 selection layer of
+     *     type OpenLayers.Layer.WMS. If not provided, layers will
+     *     be cached on the prototype. Note that if <clearOnDeactivate> is
+     *     true, the layer will no longer be cached after deactivating the
+     *     control.
+     */
+    layerCache: {},
+
+    /**
+     * Constructor: OpenLayers.Control.SLDSelect
+     * Create a new control for selecting features in WMS layers using
+     *     Styled Layer Descriptor (SLD).
+     *
+     * Parameters:
+     * handler - {<OpenLayers.Class>} A sketch handler class. This determines
+     *     the type of selection, e.g. box (<OpenLayers.Handler.Box>), point
+     *     (<OpenLayers.Handler.Point>), path (<OpenLayers.Handler.Path>) or
+     *     polygon (<OpenLayers.Handler.Polygon>) selection. To use circle
+     *     type selection, use <OpenLayers.Handler.RegularPolygon> and pass
+     *     the number of desired sides (e.g. 40) as "sides" property to the
+     *     <handlerOptions>.
+     * options - {Object} An object containing all configuration properties for
+     *     the control.
+     *
+     * Valid options:
+     * layers - Array({<OpenLayers.Layer.WMS>}) The layers to perform the
+     *     selection on.
+     */
+    initialize: function(handler, options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+        this.callbacks = OpenLayers.Util.extend({done: this.select, 
+            click: this.select}, this.callbacks);
+        this.handlerOptions = this.handlerOptions || {};
+        this.layerOptions = OpenLayers.Util.applyDefaults(this.layerOptions, {
+            displayInLayerSwitcher: false,
+            tileOptions: {maxGetUrlLength: 2048}
+        });
+        if (this.sketchStyle) {
+            this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
+                this.handlerOptions.layerOptions,
+                {styleMap: new OpenLayers.StyleMap({"default": this.sketchStyle})}
+            );
+        }
+        this.handler = new handler(this, this.callbacks, this.handlerOptions);
+    },
+
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass.
+     */
+    destroy: function() {
+        for (var key in this.layerCache) {
+            delete this.layerCache[key];
+        }
+        for (var key in this.wfsCache) {
+            delete this.wfsCache[key];
+        }
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: coupleLayerVisiblity
+     * Couple the selection layer and the source layer with respect to
+     *     layer visibility. So if the source layer is turned off, the
+     *     selection layer is also turned off.
+     *
+     * Parameters:
+     * evt - {Object}
+     */
+    coupleLayerVisiblity: function(evt) {
+        this.setVisibility(evt.object.getVisibility());
+    },
+
+    /**
+     * Method: createSelectionLayer
+     * Creates a "clone" from the source layer in which the selection can
+     * be drawn. This ensures both the source layer and the selection are 
+     * visible and not only the selection.
+     *
+     * Parameters:
+     * source - {<OpenLayers.Layer.WMS>} The source layer on which the selection
+     *     is performed.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS>} A WMS layer with maxGetUrlLength configured to 2048
+     *     since SLD selections can easily get quite long.
+     */
+    createSelectionLayer: function(source) {
+        // check if we already have a selection layer for the source layer
+        var selectionLayer;
+        if (!this.layerCache[source.id]) {
+            selectionLayer = new OpenLayers.Layer.WMS(source.name, 
+                source.url, source.params, 
+                OpenLayers.Util.applyDefaults(
+                    this.layerOptions,
+                    source.getOptions())
+            );
+            this.layerCache[source.id] = selectionLayer;
+            // make sure the layers are coupled wrt visibility, but only
+            // if they are not displayed in the layer switcher, because in
+            // that case the user cannot control visibility.
+            if (this.layerOptions.displayInLayerSwitcher === false) {
+                source.events.on({
+                    "visibilitychanged": this.coupleLayerVisiblity,
+                    scope: selectionLayer});
+            }
+            this.map.addLayer(selectionLayer);
+        } else {
+            selectionLayer = this.layerCache[source.id];
+        }
+        return selectionLayer;
+    },
+
+    /**
+     * Method: createSLD
+     * Create the SLD document for the layer using the supplied filters.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMS>}
+     * filters - Array({<OpenLayers.Filter>}) The filters to be applied.
+     * geometryAttributes - Array({Object}) The geometry attributes of the 
+     *     layer.
+     *
+     * Returns:
+     * {String} The SLD document generated as a string.
+     */
+    createSLD: function(layer, filters, geometryAttributes) {
+        var sld = {version: "1.0.0", namedLayers: {}};
+        var layerNames = [layer.params.LAYERS].join(",").split(",");
+        for (var i=0, len=layerNames.length; i<len; i++) { 
+            var name = layerNames[i];
+            sld.namedLayers[name] = {name: name, userStyles: []};
+            var symbolizer = this.selectionSymbolizer;
+            var geometryAttribute = geometryAttributes[i];
+            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
+                symbolizer = {Polygon: this.selectionSymbolizer['Polygon']};
+            } else if (geometryAttribute.type.indexOf('LineString') >= 0) {
+                symbolizer = {Line: this.selectionSymbolizer['Line']};
+            } else if (geometryAttribute.type.indexOf('Point') >= 0) {
+                symbolizer = {Point: this.selectionSymbolizer['Point']};
+            }
+            var filter = filters[i];
+            sld.namedLayers[name].userStyles.push({name: 'default', rules: [
+                new OpenLayers.Rule({symbolizer: symbolizer, 
+                    filter: filter, 
+                    maxScaleDenominator: layer.options.minScale})
+            ]});
+        }
+        return new OpenLayers.Format.SLD().write(sld);
+    },
+
+    /**
+     * Method: parseDescribeLayer
+     * Parse the SLD WMS DescribeLayer response and issue the corresponding
+     *     WFS DescribeFeatureType request
+     *
+     * request - {XMLHttpRequest} The request object.
+     */
+    parseDescribeLayer: function(request) {
+        var format = new OpenLayers.Format.WMSDescribeLayer();
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        var describeLayer = format.read(doc);
+        var typeNames = [];
+        var url = null;
+        for (var i=0, len=describeLayer.length; i<len; i++) {
+            // perform a WFS DescribeFeatureType request
+            if (describeLayer[i].owsType == "WFS") {
+                typeNames.push(describeLayer[i].typeName);
+                url = describeLayer[i].owsURL;
+            }
+        }
+        var options = {
+            url: url,
+            params: {
+                SERVICE: "WFS",
+                TYPENAME: typeNames.toString(),
+                REQUEST: "DescribeFeatureType",
+                VERSION: "1.0.0"
+            },
+            callback: function(request) {
+                var format = new OpenLayers.Format.WFSDescribeFeatureType();
+                var doc = request.responseXML;
+                if(!doc || !doc.documentElement) {
+                    doc = request.responseText;
+                }
+                var describeFeatureType = format.read(doc);
+                this.control.wfsCache[this.layer.id] = describeFeatureType;
+                this.control._queue && this.control.applySelection();
+            },
+            scope: this
+        };
+        OpenLayers.Request.GET(options);
+    },
+
+   /**
+    * Method: getGeometryAttributes
+    * Look up the geometry attributes from the WFS DescribeFeatureType response
+    *
+    * Parameters:
+    * layer - {<OpenLayers.Layer.WMS>} The layer for which to look up the 
+    *     geometry attributes.
+    *
+    * Returns:
+    * Array({Object}) Array of geometry attributes
+    */ 
+   getGeometryAttributes: function(layer) {
+        var result = [];
+        var cache = this.wfsCache[layer.id];
+        for (var i=0, len=cache.featureTypes.length; i<len; i++) {
+            var typeName = cache.featureTypes[i];
+            var properties = typeName.properties;
+            for (var j=0, lenj=properties.length; j < lenj; j++) {
+                var property = properties[j];
+                var type = property.type;
+                if ((type.indexOf('LineString') >= 0) ||
+                    (type.indexOf('GeometryAssociationType') >=0) ||
+                    (type.indexOf('GeometryPropertyType') >= 0) ||
+                    (type.indexOf('Point') >= 0) ||
+                    (type.indexOf('Polygon') >= 0) ) {
+                        result.push(property);
+                }
+            }
+        }
+        return result;
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the control. Activating the control will perform a SLD WMS
+     *     DescribeLayer request followed by a WFS DescribeFeatureType request
+     *     so that the proper symbolizers can be chosen based on the geometry
+     *     type.
+     */
+    activate: function() {
+        var activated = OpenLayers.Control.prototype.activate.call(this);
+        if(activated) {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                if (layer && !this.wfsCache[layer.id]) {
+                    var options = {
+                        url: layer.url,
+                        params: {
+                            SERVICE: "WMS",
+                            VERSION: layer.params.VERSION,
+                            LAYERS: layer.params.LAYERS,
+                            REQUEST: "DescribeLayer"
+                        },
+                        callback: this.parseDescribeLayer,
+                        scope: {layer: layer, control: this}
+                    };
+                    OpenLayers.Request.GET(options);
+                }
+            }
+        }
+        return activated;
+    },
+
+    /**
+     * APIMethod: deactivate
+     * Deactivate the control. If clearOnDeactivate is true, remove the
+     *     selection layer(s).
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
+        if(deactivated) {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                if (layer && this.clearOnDeactivate === true) {
+                    var layerCache = this.layerCache;
+                    var selectionLayer = layerCache[layer.id];
+                    if (selectionLayer) {
+                        layer.events.un({
+                            "visibilitychanged": this.coupleLayerVisiblity,
+                            scope: selectionLayer});
+                        selectionLayer.destroy();
+                        delete layerCache[layer.id];
+                    }
+                }
+            }
+        }
+        return deactivated;
+    },
+
+    /**
+     * APIMethod: setLayers
+     * Set the layers on which the selection should be performed.  Call the 
+     *     setLayers method if the layer(s) to be used change and the same 
+     *     control should be used on a new set of layers.
+     *     If the control is already active, it will be active after the new
+     *     set of layers is set.
+     *
+     * Parameters:
+     * layers - {Array(<OpenLayers.Layer.WMS>)}  The new set of layers on which 
+     *     the selection should be performed.
+     */
+    setLayers: function(layers) {
+        if(this.active) {
+            this.deactivate();
+            this.layers = layers;
+            this.activate();
+        } else {
+            this.layers = layers;
+        }
+    },
+
+    /**
+     * Function: createFilter
+     * Create the filter to be used in the SLD.
+     *
+     * Parameters:
+     * geometryAttribute - {Object} Used to get the name of the geometry 
+     *     attribute which is needed for constructing the spatial filter.
+     * geometry - {<OpenLayers.Geometry>} The geometry to use.
+     *
+     * Returns:
+     * {<OpenLayers.Filter.Spatial>} The spatial filter created.
+     */
+    createFilter: function(geometryAttribute, geometry) {
+        var filter = null;
+        if (this.handler instanceof OpenLayers.Handler.RegularPolygon) {
+            // box
+            if (this.handler.irregular === true) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.BBOX,
+                    property: geometryAttribute.name,
+                    value: geometry.getBounds()}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            }
+        } else if (this.handler instanceof OpenLayers.Handler.Polygon) {
+            filter = new OpenLayers.Filter.Spatial({
+                type: OpenLayers.Filter.Spatial.INTERSECTS,
+                property: geometryAttribute.name,
+                value: geometry}
+            );
+        } else if (this.handler instanceof OpenLayers.Handler.Path) {
+            // if source layer is point based, use DWITHIN instead
+            if (geometryAttribute.type.indexOf('Point') >= 0) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.DWITHIN,
+                    property: geometryAttribute.name,
+                    distance: this.map.getExtent().getWidth()*0.01 ,
+                    distanceUnits: this.map.getUnits(),
+                    value: geometry}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            }
+        } else if (this.handler instanceof OpenLayers.Handler.Click) {
+            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.INTERSECTS,
+                    property: geometryAttribute.name,
+                    value: geometry}
+                );
+            } else {
+                filter = new OpenLayers.Filter.Spatial({
+                    type: OpenLayers.Filter.Spatial.DWITHIN,
+                    property: geometryAttribute.name,
+                    distance: this.map.getExtent().getWidth()*0.01 ,
+                    distanceUnits: this.map.getUnits(),
+                    value: geometry}
+                );
+            }
+        }
+        return filter;
+    },
+
+    /**
+     * Method: select
+     * When the handler is done, use SLD_BODY on the selection layer to
+     *     display the selection in the map.
+     *
+     * Parameters:
+     * geometry - {Object} or {<OpenLayers.Geometry>}
+     */
+    select: function(geometry) {
+        this._queue = function() {
+            for (var i=0, len=this.layers.length; i<len; i++) {
+                var layer = this.layers[i];
+                var geometryAttributes = this.getGeometryAttributes(layer);
+                var filters = [];
+                for (var j=0, lenj=geometryAttributes.length; j<lenj; j++) {
+                    var geometryAttribute = geometryAttributes[j];
+                    if (geometryAttribute !== null) {
+                        // from the click handler we will not get an actual 
+                        // geometry so transform
+                        if (!(geometry instanceof OpenLayers.Geometry)) {
+                            var point = this.map.getLonLatFromPixel(
+                                geometry.xy);
+                            geometry = new OpenLayers.Geometry.Point(
+                                point.lon, point.lat);
+                        }
+                        var filter = this.createFilter(geometryAttribute,
+                        geometry);
+                        if (filter !== null) {
+                            filters.push(filter);
+                        }
+                    }
+                }
+    
+                var selectionLayer = this.createSelectionLayer(layer);
+                var sld = this.createSLD(layer, filters, geometryAttributes);
+    
+                this.events.triggerEvent("selected", {
+                    layer: layer,
+                    filters: filters
+                });
+    
+                selectionLayer.mergeNewParams({SLD_BODY: sld});
+                delete this._queue;
+            }
+        };
+        this.applySelection();
+    },
+    
+    /**
+     * Method: applySelection
+     * Checks if all required wfs data is cached, and applies the selection
+     */
+    applySelection: function() {
+        var canApply = true;
+        for (var i=0, len=this.layers.length; i<len; i++) {
+            if(!this.wfsCache[this.layers[i].id]) {
+                canApply = false;
+                break;
+            }
+        }
+        canApply && this._queue.call(this);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.SLDSelect"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Scale.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Scale.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Scale.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -24,6 +25,15 @@
     element: null,
     
     /**
+     * APIProperty: geodesic
+     * {Boolean} Use geodesic measurement. Default is false. The recommended
+     * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
+     * true, the scale will be calculated based on the horizontal size of the
+     * pixel in the center of the map viewport.
+     */
+    geodesic: false,
+
+    /**
      * Constructor: OpenLayers.Control.Scale
      * 
      * Parameters:
@@ -56,7 +66,19 @@
      * Method: updateScale
      */
     updateScale: function() {
-        var scale = this.map.getScale();
+        var scale;
+        if(this.geodesic === true) {
+            var units = this.map.getUnits();
+            if(!units) {
+                return;
+            }
+            var inches = OpenLayers.INCHES_PER_UNIT;
+            scale = (this.map.getGeodesicPixelSize().w || 0.000001) *
+                    inches["km"] * OpenLayers.DOTS_PER_INCH;
+        } else {
+            scale = this.map.getScale();
+        }
+            
         if (!scale) {
             return;
         }

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ScaleLine.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ScaleLine.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ScaleLine.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Control.js
@@ -61,6 +62,15 @@
      * {DOMElement}
      */
     eBottom:null,
+    
+    /**
+     * APIProperty: geodesic
+     * {Boolean} Use geodesic measurement. Default is false. The recommended
+     * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
+     * true, the scale will be calculated based on the horizontal size of the
+     * pixel in the center of the map viewport.
+     */
+    geodesic: false,
 
     /**
      * Constructor: OpenLayers.Control.ScaleLine
@@ -83,9 +93,6 @@
     draw: function() {
         OpenLayers.Control.prototype.draw.apply(this, arguments);
         if (!this.eTop) {
-            this.div.style.display = "block";
-            this.div.style.position = "absolute";
-            
             // stick in the top bar
             this.eTop = document.createElement("div");
             this.eTop.className = this.displayClass + "Top";
@@ -159,7 +166,15 @@
         var inches = OpenLayers.INCHES_PER_UNIT;
 
         // convert maxWidth to map units
-        var maxSizeData = this.maxWidth * res * inches[curMapUnits];  
+        var maxSizeData = this.maxWidth * res * inches[curMapUnits];
+        var geodesicRatio = 1;
+        if(this.geodesic === true) {
+            var maxSizeGeodesic = (this.map.getGeodesicPixelSize().w ||
+                0.000001) * this.maxWidth;
+            var maxSizeKilometers = maxSizeData / inches["km"];
+            geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
+            maxSizeData *= geodesicRatio;
+        }
 
         // decide whether to use large or small scale units     
         var topUnits;
@@ -185,8 +200,8 @@
         bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
 
         // and to pixel units
-        var topPx = topMax / res;
-        var bottomPx = bottomMax / res;
+        var topPx = topMax / res / geodesicRatio;
+        var bottomPx = bottomMax / res / geodesicRatio;
         
         // now set the pixel widths
         // and the values inside them

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/SelectFeature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/SelectFeature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/SelectFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -182,16 +183,7 @@
         if(this.scope === null) {
             this.scope = this;
         }
-        if(layers instanceof Array) {
-            this.layers = layers;
-            this.layer = new OpenLayers.Layer.Vector.RootContainer(
-                this.id + "_container", {
-                    layers: layers
-                }
-            );
-        } else {
-            this.layer = layers;
-        }
+        this.initLayer(layers);
         var callbacks = {
             click: this.clickFeature,
             clickout: this.clickoutFeature
@@ -216,11 +208,35 @@
             ); 
         }
     },
+
+    /**
+     * Method: initLayer
+     * Assign the layer property. If layers is an array, we need to use
+     *     a RootContainer.
+     *
+     * Parameters:
+     * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers.
+     */
+    initLayer: function(layers) {
+        if(layers instanceof Array) {
+            this.layers = layers;
+            this.layer = new OpenLayers.Layer.Vector.RootContainer(
+                this.id + "_container", {
+                    layers: layers
+                }
+            );
+        } else {
+            this.layer = layers;
+        }
+    },
     
     /**
      * Method: destroy
      */
     destroy: function() {
+        if(this.active && this.layers) {
+            this.map.removeLayer(this.layer);
+        }
         OpenLayers.Control.prototype.destroy.apply(this, arguments);
         if(this.layers) {
             this.layer.destroy();
@@ -472,6 +488,13 @@
             if(cont !== false) {
                 layer.selectedFeatures.push(feature);
                 this.highlight(feature);
+                // if the feature handler isn't involved in the feature
+                // selection (because the box handler is used or the
+                // feature is selected programatically) we fake the
+                // feature handler to allow unselecting on click
+                if(!this.handlers.feature.lastFeature) {
+                    this.handlers.feature.lastFeature = layer.selectedFeatures[0];
+                }
                 layer.events.triggerEvent("featureselected", {feature: feature});
                 this.onSelect.call(this.scope, feature);
             }
@@ -529,6 +552,11 @@
                 layer = layers[l];
                 for(var i=0, len = layer.features.length; i<len; ++i) {
                     var feature = layer.features[i];
+                    // check if the feature is displayed
+                    if (!feature.getVisibility()) {
+                        continue;
+                    }
+
                     if (this.geometryTypes == null || OpenLayers.Util.indexOf(
                             this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
                         if (bounds.toGeometry().intersects(feature.geometry)) {
@@ -558,5 +586,28 @@
         OpenLayers.Control.prototype.setMap.apply(this, arguments);
     },
     
+    /**
+     * APIMethod: setLayer
+     * Attach a new layer to the control, overriding any existing layers.
+     *
+     * Parameters:
+     * layers - Array of {<OpenLayers.Layer.Vector>} or a single
+     *     {<OpenLayers.Layer.Vector>}
+     */
+    setLayer: function(layers) {
+        var isActive = this.active;
+        this.unselectAll();
+        this.deactivate();
+        if(this.layers) {
+            this.layer.destroy();
+            this.layers = null;
+        }
+        this.initLayer(layers);
+        this.handlers.feature.layer = this.layer;
+        if (isActive) {
+            this.activate();
+        }
+    },
+    
     CLASS_NAME: "OpenLayers.Control.SelectFeature"
 });

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Snapping.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Snapping.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Snapping.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/Split.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/Split.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/Split.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -346,12 +347,12 @@
      * {Boolean} The supplied feature was split (and destroyed).
      */
     considerSplit: function(feature) {
-        sourceSplit = false;
-        targetSplit = false;
+        var sourceSplit = false;
+        var targetSplit = false;
         if(!this.sourceFilter ||
            this.sourceFilter.evaluate(feature.attributes)) {
             var features = this.layer && this.layer.features || [];
-            var target, results, result, proceed;
+            var target, results, proceed;
             var additions = [], removals = [];
             var mutual = (this.layer === this.source) && this.mutual;
             var options = {

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Control/TransformFeature.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Control/TransformFeature.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/TransformFeature.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/TransformFeature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,579 @@
+/* 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/Control.js
+ * @requires OpenLayers/Control/DragFeature.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TransformFeature
+ * Control to transform features with a standard transformation box.
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TransformFeature = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     *  - *beforesetfeature* Triggered before a feature is set for
+     *      tranformation. The feature will not be set if a listener returns
+     *      false. Listeners receive a *feature* property, with the feature
+     *      that will be set for transformation. Listeners are allowed to
+     *      set the control's *scale*, *ratio* and *rotation* properties,
+     *      which will set the initial scale, ratio and rotation of the
+     *      feature, like the <setFeature> method's initialParams argument.
+     *  - *setfeature* Triggered when a feature is set for tranformation.
+     *      Listeners receive a *feature* property, with the feature that
+     *      is now set for transformation.
+     *  - *beforetransform* Triggered while dragging, before a feature is
+     *      transformed. The feature will not be transformed if a listener
+     *      returns false (but the box still will). Listeners receive one or
+     *      more of *center*, *scale*, *ratio* and *rotation*. The *center*
+     *      property is an <OpenLayers.Geometry.Point> object with the new
+     *      center of the transformed feature, the others are Floats with the
+     *      scale, ratio or rotation change since the last transformation.
+     *  - *transform* Triggered while dragging, when a feature is transformed.
+     *      Listeners receive an event object with one or more of *center*,
+     *      *scale*, *ratio* and *rotation*. The *center* property is an
+     *      <OpenLayers.Geometry.Point> object with the new center of the
+     *      transformed feature, the others are Floats with the scale, ratio
+     *      or rotation change of the feature since the last transformation.
+     *  - *transformcomplete* Triggered after dragging. Listeners receive
+     *      an event object with the transformed *feature*.
+     */
+    EVENT_TYPES: ["beforesetfeature", "setfeature", "beforetransform",
+        "transform", "transformcomplete"],
+
+    /**
+     * APIProperty: geometryTypes
+     * {Array(String)} To restrict transformation to a limited set of geometry
+     *     types, send a list of strings corresponding to the geometry class
+     *     names.
+     */
+    geometryTypes: null,
+
+    /**
+     * Property: layer
+     * {<OpenLayers.Layer.Vector>}
+     */
+    layer: null,
+    
+    /**
+     * APIProperty: preserveAspectRatio
+     * {Boolean} set to true to not change the feature's aspect ratio.
+     */
+    preserveAspectRatio: false,
+    
+    /**
+     * APIProperty: rotate
+     * {Boolean} set to false if rotation should be disabled. Default is true.
+     *     To be passed with the constructor or set when the control is not
+     *     active.
+     */
+    rotate: true,
+    
+    /**
+     * APIProperty: feature
+     * {<OpenLayers.Feature.Vector>} Feature currently available for
+     *     transformation. Read-only, use <setFeature> to set it manually.
+     */
+    feature: null,
+    
+    /**
+     * APIProperty: renderIntent
+     * {String|Object} Render intent for the transformation box and
+     *     handles. A symbolizer object can also be provided here.
+     */
+    renderIntent: "temporary",
+    
+    /**
+     * APIProperty: rotationHandleSymbolizer
+     * {Object|String} Optional. A custom symbolizer for the rotation handles.
+     *     A render intent can also be provided here. Defaults to
+     *     (code)
+     *     {
+     *         stroke: false,
+     *         pointRadius: 10,
+     *         fillOpacity: 0,
+     *         cursor: "pointer"
+     *     }
+     *     (end)
+     */
+    rotationHandleSymbolizer: null,
+    
+    /**
+     * APIProperty: box
+     * {<OpenLayers.Feature.Vector>} The transformation box rectangle.
+     *     Read-only.
+     */
+    box: null,
+    
+    /**
+     * APIProperty: center
+     * {<OpenLayers.Geometry.Point>} The center of the feature bounds.
+     * Read-only.
+     */
+    center: null,
+    
+    /**
+     * APIProperty: scale
+     * {Float} The scale of the feature, relative to the scale the time the
+     *     feature was set. Read-only, except for *beforesetfeature*
+     *     listeners.
+     */
+    scale: 1,
+    
+    /**
+     * APIProperty: ratio
+     * {Float} The ratio of the feature relative to the ratio the time the
+     *     feature was set. Read-only, except for *beforesetfeature*
+     *     listeners.
+     */
+    ratio: 1,
+    
+    /**
+     * Property: rotation
+     * {Integer} the current rotation angle of the box. Read-only, except for
+     *     *beforesetfeature* listeners.
+     */
+    rotation: 0,
+    
+    /**
+     * APIProperty: handles
+     * {Array(<OpenLayers.Feature.Vector>)} The 8 handles currently available
+     *     for scaling/resizing. Numbered counterclockwise, starting from the
+     *     southwest corner. Read-only.
+     */
+    handles: null,
+    
+    /**
+     * APIProperty: rotationHandles
+     * {Array(<OpenLayers.Feature.Vector>)} The 4 rotation handles currently
+     *     available for rotating. Numbered counterclockwise, starting from
+     *     the southwest corner. Read-only.
+     */
+    rotationHandles: null,
+    
+    /**
+     * Property: dragControl
+     * {<OpenLayers.Control.DragFeature>}
+     */
+    dragControl: null,
+    
+    /**
+     * Constructor: OpenLayers.Control.TransformFeature
+     * Create a new transform feature control.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.Vector>} Layer that contains features that
+     *     will be transformed.
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+    initialize: function(layer, options) {
+        // concatenate events specific to this control with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.TransformFeature.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+        this.layer = layer;
+
+        if(!this.rotationHandleSymbolizer) {
+            this.rotationHandleSymbolizer = {
+                stroke: false,
+                pointRadius: 10,
+                fillOpacity: 0,
+                cursor: "pointer"
+            };
+        }
+
+        this.createBox();
+        this.createControl();        
+    },
+    
+    /**
+     * APIMethod: activate
+     * Activates the control.
+     */
+    activate: function() {
+        var activated = false;
+        if(OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+            this.dragControl.activate();
+            this.layer.addFeatures([this.box]);
+            this.rotate && this.layer.addFeatures(this.rotationHandles);
+            this.layer.addFeatures(this.handles);        
+            activated = true;
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivates the control.
+     */
+    deactivate: function() {
+        var deactivated = false;
+        if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+            this.layer.removeFeatures(this.handles);
+            this.rotate && this.layer.removeFeatures(this.rotationHandles);
+            this.layer.removeFeatures([this.box]);
+            this.dragControl.deactivate();
+            deactivated = true;
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: setMap
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        this.dragControl.setMap(map);
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: setFeature
+     * Place the transformation box on a feature and start transforming it.
+     * If the control is not active, it will be activated.
+     * 
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     * initialParams - {Object} Initial values for rotation, scale or ratio.
+     *     Setting a rotation value here will cause the transformation box to
+     *     start rotated. Setting a scale or ratio will not affect the
+     *     transormation box, but applications may use this to keep track of
+     *     scale and ratio of a feature across multiple transforms.
+     */
+    setFeature: function(feature, initialParams) {
+        initialParams = OpenLayers.Util.applyDefaults(initialParams, {
+            rotation: 0,
+            scale: 1,
+            ratio: 1
+        });
+        var evt = {feature: feature};
+        
+        var oldRotation = this.rotation;
+        var oldCenter = this.center;
+        OpenLayers.Util.extend(this, initialParams);
+
+        if(this.events.triggerEvent("beforesetfeature", evt) === false) {
+            return;
+        }
+
+        this.feature = feature;
+        this.activate();
+
+        this._setfeature = true;
+
+        var featureBounds = this.feature.geometry.getBounds();
+        this.box.move(featureBounds.getCenterLonLat());
+        this.box.geometry.rotate(-oldRotation, oldCenter);
+        this._angle = 0;
+
+        var ll;
+        if(this.rotation) {
+            var geom = feature.geometry.clone();
+            geom.rotate(-this.rotation, this.center);
+            var box = new OpenLayers.Feature.Vector(
+                geom.getBounds().toGeometry());
+            box.geometry.rotate(this.rotation, this.center);
+            this.box.geometry.rotate(this.rotation, this.center);
+            this.box.move(box.geometry.getBounds().getCenterLonLat());
+            var llGeom = box.geometry.components[0].components[0];
+            ll = llGeom.getBounds().getCenterLonLat();
+        } else {
+            ll = new OpenLayers.LonLat(featureBounds.left, featureBounds.bottom);
+        }
+        this.handles[0].move(ll);
+        
+        delete this._setfeature;
+
+        this.events.triggerEvent("setfeature", evt);
+    },
+    
+    /**
+     * Method: createBox
+     * Creates the box with all handles and transformation handles.
+     */
+    createBox: function() {
+        var control = this;
+        
+        this.center = new OpenLayers.Geometry.Point(0, 0);
+        var box = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LineString([
+                new OpenLayers.Geometry.Point(-1, -1),
+                new OpenLayers.Geometry.Point(0, -1),
+                new OpenLayers.Geometry.Point(1, -1),
+                new OpenLayers.Geometry.Point(1, 0),
+                new OpenLayers.Geometry.Point(1, 1),
+                new OpenLayers.Geometry.Point(0, 1),
+                new OpenLayers.Geometry.Point(-1, 1),
+                new OpenLayers.Geometry.Point(-1, 0),
+                new OpenLayers.Geometry.Point(-1, -1)
+            ]), null,
+            typeof this.renderIntent == "string" ? null : this.renderIntent
+        );
+        
+        // Override for box move - make sure that the center gets updated
+        box.geometry.move = function(x, y) {
+            control._moving = true;
+            OpenLayers.Geometry.LineString.prototype.move.apply(this, arguments);
+            control.center.move(x, y);
+            delete control._moving;
+        };
+
+        // Overrides for vertex move, resize and rotate - make sure that
+        // handle and rotationHandle geometries are also moved, resized and
+        // rotated.
+        var vertexMoveFn = function(x, y) {
+            OpenLayers.Geometry.Point.prototype.move.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.move(x, y);
+            this._handle.geometry.move(x, y);
+        };
+        var vertexResizeFn = function(scale, center, ratio) {
+            OpenLayers.Geometry.Point.prototype.resize.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.resize(
+                scale, center, ratio);
+            this._handle.geometry.resize(scale, center, ratio);
+        };
+        var vertexRotateFn = function(angle, center) {
+            OpenLayers.Geometry.Point.prototype.rotate.apply(this, arguments);
+            this._rotationHandle && this._rotationHandle.geometry.rotate(
+                angle, center);
+            this._handle.geometry.rotate(angle, center);
+        };
+        
+        // Override for handle move - make sure that the box and other handles
+        // are updated, and finally transform the feature.
+        var handleMoveFn = function(x, y) {
+            var oldX = this.x, oldY = this.y;
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            if(control._moving) {
+                return;
+            }
+            var evt = control.dragControl.handlers.drag.evt;
+            var preserveAspectRatio = !control._setfeature &&
+                control.preserveAspectRatio;
+            var reshape = !preserveAspectRatio && !(evt && evt.shiftKey);
+            var oldGeom = new OpenLayers.Geometry.Point(oldX, oldY);
+            var centerGeometry = control.center;
+            this.rotate(-control.rotation, centerGeometry);
+            oldGeom.rotate(-control.rotation, centerGeometry);
+            var dx1 = this.x - centerGeometry.x;
+            var dy1 = this.y - centerGeometry.y;
+            var dx0 = dx1 - (this.x - oldGeom.x);
+            var dy0 = dy1 - (this.y - oldGeom.y);
+            this.x = oldX;
+            this.y = oldY;
+            var scale, ratio = 1;
+            if (reshape) {
+                scale = Math.abs(dy0) < 0.00001 ? 1 : dy1 / dy0;
+                ratio = (Math.abs(dx0) < 0.00001 ? 1 : (dx1 / dx0)) / scale;
+            } else {
+                var l0 = Math.sqrt((dx0 * dx0) + (dy0 * dy0));
+                var l1 = Math.sqrt((dx1 * dx1) + (dy1 * dy1));
+                scale = l1 / l0;
+            }
+
+            // rotate the box to 0 before resizing - saves us some
+            // calculations and is inexpensive because we don't drawFeature.
+            control._moving = true;
+            control.box.geometry.rotate(-control.rotation, centerGeometry);
+            delete control._moving;
+
+            control.box.geometry.resize(scale, centerGeometry, ratio);
+            control.box.geometry.rotate(control.rotation, centerGeometry);
+            control.transformFeature({scale: scale, ratio: ratio});
+        };
+        
+        // Override for rotation handle move - make sure that the box and
+        // other handles are updated, and finally transform the feature.
+        var rotationHandleMoveFn = function(x, y){
+            var oldX = this.x, oldY = this.y;
+            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
+            if(control._moving) {
+                return;
+            }
+            var evt = control.dragControl.handlers.drag.evt;
+            var constrain = (evt && evt.shiftKey) ? 45 : 1;
+            var centerGeometry = control.center;
+            var dx1 = this.x - centerGeometry.x;
+            var dy1 = this.y - centerGeometry.y;
+            var dx0 = dx1 - x;
+            var dy0 = dy1 - y;
+            this.x = oldX;
+            this.y = oldY;
+            var a0 = Math.atan2(dy0, dx0);
+            var a1 = Math.atan2(dy1, dx1);
+            var angle = a1 - a0;
+            angle *= 180 / Math.PI;
+            control._angle = (control._angle + angle) % 360;
+            var diff = control.rotation % constrain;
+            if(Math.abs(control._angle) >= constrain || diff !== 0) {
+                angle = Math.round(control._angle / constrain) * constrain -
+                    diff;
+                control._angle = 0;
+                control.box.geometry.rotate(angle, centerGeometry);
+                control.transformFeature({rotation: angle});
+            } 
+        };
+
+        var handles = new Array(8);
+        var rotationHandles = new Array(4);
+        var geom, handle, rotationHandle;
+        for(var i=0; i<8; ++i) {
+            geom = box.geometry.components[i];
+            handle = new OpenLayers.Feature.Vector(geom.clone(), null,
+                typeof this.renderIntent == "string" ? null :
+                this.renderIntent);
+            if(i % 2 == 0) {
+                rotationHandle = new OpenLayers.Feature.Vector(geom.clone(),
+                    null, typeof this.rotationHandleSymbolizer == "string" ?
+                    null : this.rotationHandleSymbolizer);
+                rotationHandle.geometry.move = rotationHandleMoveFn;
+                geom._rotationHandle = rotationHandle;
+                rotationHandles[i/2] = rotationHandle;
+            }
+            geom.move = vertexMoveFn;
+            geom.resize = vertexResizeFn;
+            geom.rotate = vertexRotateFn;
+            handle.geometry.move = handleMoveFn;
+            geom._handle = handle;
+            handles[i] = handle;
+        }
+        
+        this.box = box;
+        this.rotationHandles = rotationHandles;
+        this.handles = handles;
+    },
+    
+    /**
+     * Method: createControl
+     * Creates a DragFeature control for this control.
+     */
+    createControl: function() {
+        var control = this;
+        this.dragControl = new OpenLayers.Control.DragFeature(this.layer, {
+            documentDrag: true,
+            // avoid moving the feature itself - move the box instead
+            moveFeature: function(pixel) {
+                if(this.feature === control.feature) {
+                    this.feature = control.box;
+                }
+                OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,
+                    arguments);
+            },
+            // transform while dragging
+            onDrag: function(feature, pixel) {
+                if(feature === control.box) {
+                    control.transformFeature({center: control.center});
+                    control.drawHandles();
+                }
+            },
+            // set a new feature
+            onStart: function(feature, pixel) {
+                var eligible = !control.geometryTypes ||
+                    OpenLayers.Util.indexOf(control.geometryTypes,
+                        feature.geometry.CLASS_NAME) !== -1;
+                var i = OpenLayers.Util.indexOf(control.handles, feature);
+                i += OpenLayers.Util.indexOf(control.rotationHandles,
+                    feature);
+                if(feature !== control.feature && feature !== control.box &&
+                                                        i == -2 && eligible) {
+                    control.setFeature(feature);
+                }
+            },
+            onComplete: function(feature, pixel) {
+                control.events.triggerEvent("transformcomplete",
+                    {feature: control.feature});
+            }
+        });
+    },
+    
+    /**
+     * Method: drawHandles
+     * Draws the handles to match the box.
+     */
+    drawHandles: function() {
+        var layer = this.layer;
+        for(var i=0; i<8; ++i) {
+            if(this.rotate && i % 2 === 0) {
+                layer.drawFeature(this.rotationHandles[i/2],
+                    this.rotationHandleSymbolizer);
+            }
+            layer.drawFeature(this.handles[i], this.renderIntent);
+        }
+    },
+    
+    /**
+     * Method: transformFeature
+     * Transforms the feature.
+     * 
+     * Parameters:
+     * mods - {Object} An object with optional scale, ratio, rotation and
+     *     center properties.
+     */
+    transformFeature: function(mods) {
+        if(!this._setfeature) {
+            this.scale *= (mods.scale || 1);
+            this.ratio *= (mods.ratio || 1);
+            var oldRotation = this.rotation;
+            this.rotation = (this.rotation + (mods.rotation || 0)) % 360;
+            
+            if(this.events.triggerEvent("beforetransform", mods) !== false) {
+                var feature = this.feature;
+                var geom = feature.geometry;
+                var center = this.center;
+                geom.rotate(-oldRotation, center);
+                if(mods.scale || mods.ratio) {
+                    geom.resize(mods.scale, center, mods.ratio);
+                } else if(mods.center) {
+                    feature.move(mods.center.getBounds().getCenterLonLat());
+                }
+                geom.rotate(this.rotation, center);
+                this.layer.drawFeature(feature);
+                feature.toState(OpenLayers.State.UPDATE);
+                this.events.triggerEvent("transform", mods);
+            }
+        }
+        this.layer.drawFeature(this.box, this.renderIntent);
+        this.drawHandles();
+    },
+        
+    /**
+     * APIMethod: destroy
+     * Take care of things that are not handled in superclass.
+     */
+    destroy: function() {
+        var geom;
+        for(var i=0; i<8; ++i) {
+            geom = this.box.geometry.components[i];
+            geom._handle.destroy();
+            geom._handle = null;
+            geom._rotationHandle && geom._rotationHandle.destroy();
+            geom._rotationHandle = null;
+        }
+        this.box.destroy();
+        this.box = null;
+        this.layer = null;
+        this.dragControl.destroy();
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.TransformFeature"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/WMSGetFeatureInfo.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/WMSGetFeatureInfo.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/WMSGetFeatureInfo.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -23,7 +24,7 @@
  *  - <OpenLayers.Control>
  */
 OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
-    
+
    /**
      * APIProperty: hover
      * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
@@ -32,18 +33,33 @@
     hover: false,
 
     /**
+     * APIProperty: drillDown
+     * {Boolean} Drill down over all WMS layers in the map. When
+     *     using drillDown mode, hover is not possible, and an infoFormat that
+     *     returns parseable features is required. Default is false.
+     */
+    drillDown: false,
+
+    /**
      * APIProperty: maxFeatures
      * {Integer} Maximum number of features to return from a WMS query. This
      *     sets the feature_count parameter on WMS GetFeatureInfo
      *     requests.
      */
     maxFeatures: 10,
+
+    /** APIProperty: clickCallback
+     *  {String} The click callback to register in the
+     *      {<OpenLayers.Handler.Click>} object created when the hover
+     *      option is set to false. Default is "click".
+     */
+    clickCallback: "click",
     
     /**
      * Property: layers
      * {Array(<OpenLayers.Layer.WMS>)} The layers to query for feature info.
      *     If omitted, all map WMS layers with a url that matches this <url> or
-     *     <layerUrl> will be considered.
+     *     <layerUrls> will be considered.
      */
     layers: null,
 
@@ -131,14 +147,21 @@
      * Constant: EVENT_TYPES
      *
      * Supported event types (in addition to those from <OpenLayers.Control>):
+     * beforegetfeatureinfo - Triggered before the request is sent.
+     *      The event object has an *xy* property with the position of the 
+     *      mouse click or hover event that triggers the request.
+     * nogetfeatureinfo - no queryable layers were found.
      * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
      *      The event object has a *text* property with the body of the
      *      response (String), a *features* property with an array of the
      *      parsed features, an *xy* property with the position of the mouse
      *      click or hover event that triggered the request, and a *request*
-     *      property with the request itself.
+     *      property with the request itself. If drillDown is set to true and
+     *      multiple requests were issued to collect feature info from all
+     *      layers, *text* and *request* will only contain the response body
+     *      and request object of the last request.
      */
-    EVENT_TYPES: ["getfeatureinfo"],
+    EVENT_TYPES: ["beforegetfeatureinfo", "nogetfeatureinfo", "getfeatureinfo"],
 
     /**
      * Constructor: <OpenLayers.Control.WMSGetFeatureInfo>
@@ -163,8 +186,12 @@
                 options.formatOptions
             );
         }
+        
+        if(this.drillDown === true) {
+            this.hover = false;
+        }
 
-        if (this.hover) {
+        if(this.hover) {
             this.handler = new OpenLayers.Handler.Hover(
                    this, {
                        'move': this.cancelHover,
@@ -174,8 +201,10 @@
                        'delay': 250
                    }));
         } else {
-            this.handler = new OpenLayers.Handler.Click(this,
-                {click: this.getInfoForClick}, this.handlerOptions.click || {});
+            var callbacks = {};
+            callbacks[this.clickCallback] = this.getInfoForClick;
+            this.handler = new OpenLayers.Handler.Click(
+                this, callbacks, this.handlerOptions.click || {});
         }
     },
 
@@ -216,6 +245,7 @@
      * evt - {<OpenLayers.Event>} 
      */
     getInfoForClick: function(evt) {
+        this.events.triggerEvent("beforegetfeatureinfo", {xy: evt.xy});
         // Set the cursor to "wait" to tell the user we're working on their
         // click.
         OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
@@ -230,6 +260,7 @@
      * evt - {Object}
      */
     getInfoForHover: function(evt) {
+        this.events.triggerEvent("beforegetfeatureinfo", {xy: evt.xy});
         this.request(evt.xy, {hover: true});
     },
 
@@ -251,9 +282,8 @@
      */
     findLayers: function() {
 
+        var candidates = this.layers || this.map.layers;
         var layers = [];
-        
-        var candidates = this.layers || this.map.layers;
         var layer, url;
         for(var i=0, len=candidates.length; i<len; ++i) {
             layer = candidates[i];
@@ -262,15 +292,14 @@
                 url = layer.url instanceof Array ? layer.url[0] : layer.url;
                 // if the control was not configured with a url, set it
                 // to the first layer url
-                if(!this.url) {
+                if(this.drillDown === false && !this.url) {
                     this.url = url;
                 }
-                if(this.urlMatches(url)) {
+                if(this.drillDown === true || this.urlMatches(url)) {
                     layers.push(layer);
                 }
             }
         }
-
         return layers;
     },
     
@@ -300,6 +329,89 @@
     },
 
     /**
+     * Method: buildWMSOptions
+     * Build an object with the relevant WMS options for the GetFeatureInfo request
+     *
+     * Parameters:
+     * url - {String} The url to be used for sending the request
+     * layers - {Array(<OpenLayers.Layer.WMS)} An array of layers
+     * clickPosition - {<OpenLayers.Pixel>} The position on the map where the mouse
+     *     event occurred.
+     * format - {String} The format from the corresponding GetMap request
+     */
+    buildWMSOptions: function(url, layers, clickPosition, format) {
+        var layerNames = [], styleNames = [];
+        for (var i = 0, len = layers.length; i < len; i++) { 
+            layerNames = layerNames.concat(layers[i].params.LAYERS);
+            styleNames = styleNames.concat(this.getStyleNames(layers[i]));
+        }
+        var params = OpenLayers.Util.extend({
+            service: "WMS",
+            version: layers[0].params.VERSION,
+            request: "GetFeatureInfo",
+            layers: layerNames,
+            query_layers: layerNames,
+            styles: styleNames,
+            bbox: this.map.getExtent().toBBOX(null,
+                layers[0].reverseAxisOrder()),
+            feature_count: this.maxFeatures,
+            height: this.map.getSize().h,
+            width: this.map.getSize().w,
+            format: format,
+            info_format: this.infoFormat
+        }, (parseFloat(layers[0].params.VERSION) >= 1.3) ?
+            {
+                crs: this.map.getProjection(),
+                i: clickPosition.x,
+                j: clickPosition.y
+            } :
+            {
+                srs: this.map.getProjection(),
+                x: clickPosition.x,
+                y: clickPosition.y
+            }
+        );
+        OpenLayers.Util.applyDefaults(params, this.vendorParams);
+        return {
+            url: url,
+            params: OpenLayers.Util.upperCaseObject(params),
+            callback: function(request) {
+                this.handleResponse(clickPosition, request);
+            },
+            scope: this
+        };
+    },
+
+    /**
+     * Method: getStyleNames
+     * Gets the STYLES parameter for the layer. Make sure the STYLES parameter
+     * matches the LAYERS parameter
+     * 
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMS>}
+     *
+     * Returns:
+     * {Array(String)} The STYLES parameter
+     */
+    getStyleNames: function(layer) {
+        // in the event of a WMS layer bundling multiple layers but not
+        // specifying styles,we need the same number of commas to specify
+        // the default style for each of the layers.  We can't just leave it
+        // blank as we may be including other layers that do specify styles.
+        var styleNames;
+        if (layer.params.STYLES) {
+            styleNames = layer.params.STYLES;
+        } else {
+            if (layer.params.LAYERS instanceof Array) {
+                styleNames = new Array(layer.params.LAYERS.length);
+            } else { // Assume it's a String
+                styleNames = layer.params.LAYERS.replace(/[^,]/g, "");
+            }
+        }
+        return styleNames;
+    },
+
+    /**
      * Method: request
      * Sends a GetFeatureInfo request to the WMS
      * 
@@ -312,64 +424,71 @@
      * - *hover* {Boolean} true if we do the request for the hover handler
      */
     request: function(clickPosition, options) {
+        var layers = this.findLayers();
+        if(layers.length == 0) {
+            this.events.triggerEvent("nogetfeatureinfo");
+            // Reset the cursor.
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+            return;
+        }
+        
         options = options || {};
-        var layerNames = [];
-        var styleNames = [];
-
-        var layers = this.findLayers();
-        if(layers.length > 0) {
-
-            for (var i = 0, len = layers.length; i < len; i++) { 
-                layerNames = layerNames.concat(layers[i].params.LAYERS);
-                // in the event of a WMS layer bundling multiple layers but not
-                // specifying styles,we need the same number of commas to specify
-                // the default style for each of the layers.  We can't just leave it
-                // blank as we may be including other layers that do specify styles.
-                if (layers[i].params.STYLES) {
-                    styleNames = styleNames.concat(layers[i].params.STYLES);
+        if(this.drillDown === false) {
+            var wmsOptions = this.buildWMSOptions(this.url, layers,
+                clickPosition, layers[0].params.FORMAT); 
+            var request = OpenLayers.Request.GET(wmsOptions);
+    
+            if (options.hover === true) {
+                this.hoverRequest = request;
+            }
+        } else {
+            this._requestCount = 0;
+            this._numRequests = 0;
+            this.features = [];
+            // group according to service url to combine requests
+            var services = {}, url;
+            for(var i=0, len=layers.length; i<len; i++) {
+                var layer = layers[i];
+                var service, found = false;
+                url = layer.url instanceof Array ? layer.url[0] : layer.url;
+                if(url in services) {
+                    services[url].push(layer);
                 } else {
-                    if (layers[i].params.LAYERS instanceof Array) {
-                        styleNames = styleNames.concat(new Array(layers[i].params.LAYERS.length));
-                    } else { // Assume it's a String
-                        styleNames = styleNames.concat(layers[i].params.LAYERS.replace(/[^,]/g, ""));
-                    }
+                    this._numRequests++;
+                    services[url] = [layer];
                 }
             }
-    
-            var wmsOptions = {
-                url: this.url,
-                params: OpenLayers.Util.applyDefaults({
-                    service: "WMS",
-                    version: "1.1.0",
-                    request: "GetFeatureInfo",
-                    layers: layerNames,
-                    query_layers: layerNames,
-                    styles: styleNames,
-                    bbox: this.map.getExtent().toBBOX(),
-                    srs: this.map.getProjection(),
-                    feature_count: this.maxFeatures,
-                    x: clickPosition.x,
-                    y: clickPosition.y,
-                    height: this.map.getSize().h,
-                    width: this.map.getSize().w,
-                    info_format: this.infoFormat 
-                }, this.vendorParams), 
-                callback: function(request) {
-                    this.handleResponse(clickPosition, request);
-                },
-                scope: this                    
-            };
-    
-            var response = OpenLayers.Request.GET(wmsOptions);
-    
-            if (options.hover === true) {
-                this.hoverRequest = response.priv;
+            var layers;
+            for (var url in services) {
+                layers = services[url];
+                var wmsOptions = this.buildWMSOptions(url, layers, 
+                    clickPosition, layers[0].params.FORMAT);
+                OpenLayers.Request.GET(wmsOptions); 
             }
-        } else {
-            // Reset the cursor.
-            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
         }
     },
+
+    /**
+     * Method: triggerGetFeatureInfo
+     * Trigger the getfeatureinfo event when all is done
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     * xy - {<OpenLayers.Pixel>} The position on the map where the
+     *     mouse event occurred.
+     * features - {Array(<OpenLayers.Feature.Vector>)}
+     */
+    triggerGetFeatureInfo: function(request, xy, features) {
+        this.events.triggerEvent("getfeatureinfo", {
+            text: request.responseText,
+            features: features,
+            request: request,
+            xy: xy
+        });
+
+        // Reset the cursor.
+        OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+    },
     
     /**
      * Method: handleResponse
@@ -387,29 +506,19 @@
             doc = request.responseText;
         }
         var features = this.format.read(doc);
-
-        this.events.triggerEvent("getfeatureinfo", {
-            text: request.responseText,
-            features: features,
-            request: request,
-            xy: xy
-        });
-        
-        // Reset the cursor.
-        OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+        if (this.drillDown === false) {
+            this.triggerGetFeatureInfo(request, xy, features);
+        } else {
+            this._requestCount++;
+            this._features = (this._features || []).concat(features);
+            if (this._requestCount === this._numRequests) {
+                this.triggerGetFeatureInfo(request, xy, this._features.concat()); 
+                delete this._features;
+                delete this._requestCount;
+                delete this._numRequests;
+            }
+        }
     },
-   
-    /** 
-     * Method: setMap
-     * Set the map property for the control. 
-     * 
-     * Parameters:
-     * map - {<OpenLayers.Map>} 
-     */
-    setMap: function(map) {
-        this.handler.setMap(map);
-        OpenLayers.Control.prototype.setMap.apply(this, arguments);
-    },
 
     CLASS_NAME: "OpenLayers.Control.WMSGetFeatureInfo"
 });

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Control/WMTSGetFeatureInfo.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Control/WMTSGetFeatureInfo.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/WMTSGetFeatureInfo.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/WMTSGetFeatureInfo.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,401 @@
+/* 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/Control.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Handler/Hover.js
+ * @requires OpenLayers/Request.js
+ * @requires OpenLayers/Format/WMSGetFeatureInfo.js
+ */
+
+/**
+ * Class: OpenLayers.Control.WMTSGetFeatureInfo
+ * The WMTSGetFeatureInfo control uses a WMTS query to get information about a 
+ *     point on the map.  The information may be in a display-friendly format 
+ *     such as HTML, or a machine-friendly format such as GML, depending on the 
+ *     server's capabilities and the client's configuration.  This control 
+ *     handles click or hover events, attempts to parse the results using an 
+ *     OpenLayers.Format, and fires a 'getfeatureinfo' event for each layer
+ *     queried.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.WMTSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
+
+   /**
+     * APIProperty: hover
+     * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
+     *     Default is false.
+     */
+    hover: false,
+    
+    /**
+     * Property: requestEncoding
+     * {String} One of "KVP" or "REST".  Only KVP encoding is supported at this 
+     *     time.
+     */
+    requestEncoding: "KVP",
+
+    /**
+     * APIProperty: drillDown
+     * {Boolean} Drill down over all WMTS layers in the map. When
+     *     using drillDown mode, hover is not possible.  A getfeatureinfo event
+     *     will be fired for each layer queried.
+     */
+    drillDown: false,
+
+    /**
+     * APIProperty: maxFeatures
+     * {Integer} Maximum number of features to return from a WMTS query. This
+     *     sets the feature_count parameter on WMTS GetFeatureInfo
+     *     requests.
+     */
+    maxFeatures: 10,
+
+    /** APIProperty: clickCallback
+     *  {String} The click callback to register in the
+     *      {<OpenLayers.Handler.Click>} object created when the hover
+     *      option is set to false. Default is "click".
+     */
+    clickCallback: "click",
+    
+    /**
+     * Property: layers
+     * {Array(<OpenLayers.Layer.WMTS>)} The layers to query for feature info.
+     *     If omitted, all map WMTS layers will be considered.
+     */
+    layers: null,
+
+    /**
+     * APIProperty: queryVisible
+     * {Boolean} Filter out hidden layers when searching the map for layers to 
+     *     query.  Default is true.
+     */
+    queryVisible: true,
+
+    /**
+     * Property: infoFormat
+     * {String} The mimetype to request from the server
+     */
+    infoFormat: 'text/html',
+    
+    /**
+     * Property: vendorParams
+     * {Object} Additional parameters that will be added to the request, for
+     * WMTS implementations that support them. This could e.g. look like
+     * (start code)
+     * {
+     *     radius: 5
+     * }
+     * (end)
+     */
+    vendorParams: {},
+    
+    /**
+     * Property: format
+     * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
+     *     Default is <OpenLayers.Format.WMSGetFeatureInfo>.
+     */
+    format: null,
+    
+    /**
+     * Property: formatOptions
+     * {Object} Optional properties to set on the format (if one is not provided
+     *     in the <format> property.
+     */
+    formatOptions: null,
+
+    /**
+     * APIProperty: handlerOptions
+     * {Object} Additional options for the handlers used by this control, e.g.
+     * (start code)
+     * {
+     *     "click": {delay: 100},
+     *     "hover": {delay: 300}
+     * }
+     * (end)
+     */
+    handlerOptions: null,
+    
+    /**
+     * Property: handler
+     * {Object} Reference to the <OpenLayers.Handler> for this control
+     */
+    handler: null,
+    
+    /**
+     * Property: hoverRequest
+     * {<OpenLayers.Request>} contains the currently running hover request
+     *     (if any).
+     */
+    hoverRequest: null,
+    
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types (in addition to those from <OpenLayers.Control>):
+     * beforegetfeatureinfo - Triggered before each request is sent.
+     *      The event object has an *xy* property with the position of the 
+     *      mouse click or hover event that triggers the request and a *layer*
+     *      property referencing the layer about to be queried.  If a listener
+     *      returns false, the request will not be issued.
+     * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
+     *      The event object has a *text* property with the body of the
+     *      response (String), a *features* property with an array of the
+     *      parsed features, an *xy* property with the position of the mouse
+     *      click or hover event that triggered the request, a *layer* property
+     *      referencing the layer queried and a *request* property with the 
+     *      request itself. If drillDown is set to true, one event will be fired
+     *      for each layer queried.
+     * exception - Triggered when a GetFeatureInfo request fails (with a 
+     *      status other than 200) or whenparsing fails.  Listeners will receive 
+     *      an event with *request*, *xy*, and *layer*  properties.  In the case 
+     *      of a parsing error, the event will also contain an *error* property.
+     */
+    EVENT_TYPES: ["beforegetfeatureinfo", "getfeatureinfo", "exception"],
+    
+    /** 
+     * Property: pending
+     * {Number}  The number of pending requests.
+     */
+    pending: 0,
+
+    /**
+     * Constructor: <OpenLayers.Control.WMTSGetFeatureInfo>
+     *
+     * Parameters:
+     * options - {Object} 
+     */
+    initialize: function(options) {
+        // concatenate events specific to vector with those from the base
+        this.EVENT_TYPES =
+            OpenLayers.Control.WMTSGetFeatureInfo.prototype.EVENT_TYPES.concat(
+            OpenLayers.Control.prototype.EVENT_TYPES
+        );
+
+        options = options || {};
+        options.handlerOptions = options.handlerOptions || {};
+
+        OpenLayers.Control.prototype.initialize.apply(this, [options]);
+        
+        if (!this.format) {
+            this.format = new OpenLayers.Format.WMSGetFeatureInfo(
+                options.formatOptions
+            );
+        }
+        
+        if (this.drillDown === true) {
+            this.hover = false;
+        }
+
+        if (this.hover) {
+            this.handler = new OpenLayers.Handler.Hover(
+                this, {
+                    move: this.cancelHover,
+                    pause: this.getInfoForHover
+                },
+                OpenLayers.Util.extend(
+                    this.handlerOptions.hover || {}, {delay: 250}
+                )
+            );
+        } else {
+            var callbacks = {};
+            callbacks[this.clickCallback] = this.getInfoForClick;
+            this.handler = new OpenLayers.Handler.Click(
+                this, callbacks, this.handlerOptions.click || {}
+            );
+        }
+    },
+
+    /**
+     * Method: getInfoForClick 
+     * Called on click
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>} 
+     */
+    getInfoForClick: function(evt) {
+        this.request(evt.xy, {});
+    },
+   
+    /**
+     * Method: getInfoForHover
+     * Pause callback for the hover handler
+     *
+     * Parameters:
+     * evt - {Object}
+     */
+    getInfoForHover: function(evt) {
+        this.request(evt.xy, {hover: true});
+    },
+
+    /**
+     * Method: cancelHover
+     * Cancel callback for the hover handler
+     */
+    cancelHover: function() {
+        if (this.hoverRequest) {
+            --this.pending;
+            if (this.pending <= 0) {
+                OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+                this.pending = 0;
+            }            
+            this.hoverRequest.abort();
+            this.hoverRequest = null;
+        }
+    },
+
+    /**
+     * Method: findLayers
+     * Internal method to get the layers, independent of whether we are
+     *     inspecting the map or using a client-provided array
+     */
+    findLayers: function() {
+        var candidates = this.layers || this.map.layers;
+        var layers = [];
+        var layer;
+        for (var i=candidates.length-1; i>=0; --i) {
+            layer = candidates[i];
+            if (layer instanceof OpenLayers.Layer.WMTS &&
+                layer.requestEncoding === this.requestEncoding &&
+                (!this.queryVisible || layer.getVisibility())) {
+                layers.push(layer);
+                if (!this.drillDown || this.hover) {
+                    break;
+                }
+            }
+        }
+        return layers;
+    },
+    
+    /**
+     * Method: buildRequestOptions
+     * Build an object with the relevant options for the GetFeatureInfo request.
+     *
+     * Parameters:
+     * layer - {<OpenLayers.Layer.WMTS>} A WMTS layer.
+     * xy - {<OpenLayers.Pixel>} The position on the map where the 
+     *     mouse event occurred.
+     */
+    buildRequestOptions: function(layer, xy) {
+        var loc = this.map.getLonLatFromPixel(xy);
+        var getTileUrl = layer.getURL(
+            new OpenLayers.Bounds(loc.lon, loc.lat, loc.lon, loc.lat)
+        );
+        var params = OpenLayers.Util.getParameters(getTileUrl);
+        var tileInfo = layer.getTileInfo(loc);
+        OpenLayers.Util.extend(params, {
+            service: "WMTS",
+            version: layer.version,
+            request: "GetFeatureInfo",
+            infoFormat: this.infoFormat,
+            i: tileInfo.i,
+            j: tileInfo.j
+        });
+        OpenLayers.Util.applyDefaults(params, this.vendorParams);
+        return {
+            url: layer.url instanceof Array ? layer.url[0] : layer.url,
+            params: OpenLayers.Util.upperCaseObject(params),
+            callback: function(request) {
+                this.handleResponse(xy, request, layer);
+            },
+            scope: this
+        };
+    },
+
+    /**
+     * Method: request
+     * Sends a GetFeatureInfo request to the WMTS
+     * 
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event 
+     *     occurred.
+     * options - {Object} additional options for this method.
+     * 
+     * Valid options:
+     * - *hover* {Boolean} true if we do the request for the hover handler
+     */
+    request: function(xy, options) {
+        options = options || {};
+        var layers = this.findLayers();
+        if (layers.length > 0) {
+            var issue, layer;
+            for (var i=0, len=layers.length; i<len; i++) {
+                layer = layers[i];
+                issue = this.events.triggerEvent("beforegetfeatureinfo", {
+                    xy: xy,
+                    layer: layer
+                });
+                if (issue !== false) {
+                    ++this.pending;
+                    var requestOptions = this.buildRequestOptions(layer, xy);
+                    var request = OpenLayers.Request.GET(requestOptions);
+                    if (options.hover === true) {
+                        this.hoverRequest = request;
+                    }
+                }
+            }
+            if (this.pending > 0) {
+                OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+            }
+        }
+    },
+
+    /**
+     * Method: handleResponse
+     * Handler for the GetFeatureInfo response.
+     * 
+     * Parameters:
+     * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event 
+     *     occurred.
+     * request - {XMLHttpRequest} The request object.
+     * layer - {<OpenLayers.Layer.WMTS>} The queried layer.
+     */
+    handleResponse: function(xy, request, layer) {
+        --this.pending;
+        if (this.pending <= 0) {
+            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+            this.pending = 0;
+        }
+        if (request.status && (request.status < 200 || request.status >= 300)) {
+            this.events.triggerEvent("exception", {
+                xy: xy, 
+                request: request,
+                layer: layer
+            });
+        } else {
+            var doc = request.responseXML;
+            if (!doc || !doc.documentElement) {
+                doc = request.responseText;
+            }
+            var features, except;
+            try {
+                features = this.format.read(doc);
+            } catch (error) {
+                except = true;
+                this.events.triggerEvent("exception", {
+                    xy: xy,
+                    request: request,
+                    error: error,
+                    layer: layer
+                });
+            }
+            if (!except) {
+                this.events.triggerEvent("getfeatureinfo", {
+                    text: request.responseText,
+                    features: features,
+                    request: request,
+                    xy: xy,
+                    layer: layer
+                });
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Control.WMTSGetFeatureInfo"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomBox.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomBox.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomBox.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -51,12 +52,13 @@
      */
     zoomBox: function (position) {
         if (position instanceof OpenLayers.Bounds) {
+            var bounds;
             if (!this.out) {
                 var minXY = this.map.getLonLatFromPixel(
                             new OpenLayers.Pixel(position.left, position.bottom));
                 var maxXY = this.map.getLonLatFromPixel(
                             new OpenLayers.Pixel(position.right, position.top));
-                var bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat,
+                bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat,
                                                maxXY.lon, maxXY.lat);
             } else {
                 var pixWidth = Math.abs(position.right-position.left);
@@ -70,7 +72,7 @@
                 var xmax = center.lon + (extent.getWidth()/2)*zoomFactor;
                 var ymin = center.lat - (extent.getHeight()/2)*zoomFactor;
                 var ymax = center.lat + (extent.getHeight()/2)*zoomFactor;
-                var bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax);
+                bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax);
             }
             // always zoom in/out 
             var lastZoom = this.map.getZoom(); 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomIn.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomIn.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomIn.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomOut.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomOut.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomOut.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomPanel.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomPanel.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomPanel.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomToMaxExtent.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomToMaxExtent.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control/ZoomToMaxExtent.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Control.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Control.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Control.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -76,9 +77,9 @@
 
     /** 
      * Property: type 
-     * {OpenLayers.Control.TYPES} Controls can have a 'type'. The type
-     * determines the type of interactions which are possible with them when
-     * they are placed into a toolbar. 
+     * {Number} Controls can have a 'type'. The type determines the type of
+     * interactions which are possible with them when they are placed in an
+     * <OpenLayers.Control.Panel>. 
      */
     type: null, 
 
@@ -105,6 +106,13 @@
     */ 
     title: "",
 
+    /**
+     * APIProperty: autoActivate
+     * {Boolean} Activate the control when it is added to a map.  Default is
+     *     false.
+     */
+    autoActivate: false,
+
     /** 
      * Property: active 
      * {Boolean} The control is active.
@@ -258,7 +266,7 @@
             if (!this.allowSelection) {
                 this.div.className += " olControlNoSelect";
                 this.div.setAttribute("unselectable", "on", 0);
-                this.div.onselectstart = function() { return(false); }; 
+                this.div.onselectstart = OpenLayers.Function.False; 
             }    
             if (this.title != "") {
                 this.div.title = this.title;
@@ -344,6 +352,17 @@
     CLASS_NAME: "OpenLayers.Control"
 });
 
+/**
+ * Constant: OpenLayers.Control.TYPE_BUTTON
+ */
 OpenLayers.Control.TYPE_BUTTON = 1;
+
+/**
+ * Constant: OpenLayers.Control.TYPE_TOGGLE
+ */
 OpenLayers.Control.TYPE_TOGGLE = 2;
+
+/**
+ * Constant: OpenLayers.Control.TYPE_TOOL
+ */
 OpenLayers.Control.TYPE_TOOL   = 3;

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Events.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Events.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Events.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -448,8 +449,8 @@
      * Construct an OpenLayers.Events object.
      *
      * Parameters:
-     * object - {Object} The js object to which this Events object  is being
-     * added element - {DOMElement} A dom element to respond to browser events
+     * object - {Object} The js object to which this Events object  is being added
+     * element - {DOMElement} A dom element to respond to browser events
      * eventTypes - {Array(String)} Array of custom application events 
      * fallThrough - {Boolean} Allow events to fall through after these have
      *                         been handled?
@@ -550,16 +551,29 @@
     },
     
     /**
-     * Method: on
+     * APIMethod: on
      * Convenience method for registering listeners with a common scope.
+     *     Internally, this method calls <register> as shown in the examples
+     *     below.
      *
      * Example use:
      * (code)
+     * // register a single listener for the "loadstart" event
+     * events.on({"loadstart", loadStartListener});
+     *
+     * // this is equivalent to the following
+     * events.register("loadstart", undefined, loadStartListener);
+     *
+     * // register multiple listeners to be called with the same `this` object
      * events.on({
      *     "loadstart": loadStartListener,
      *     "loadend": loadEndListener,
      *     scope: object
      * });
+     *
+     * // this is equivalent to the following
+     * events.register("loadstart", object, loadStartListener);
+     * events.register("loadstart", object, loadEndListener);
      * (end)
      */
     on: function(object) {
@@ -641,16 +655,29 @@
     },
     
     /**
-     * Method: un
+     * APIMethod: un
      * Convenience method for unregistering listeners with a common scope.
+     *     Internally, this method calls <unregister> as shown in the examples
+     *     below.
      *
      * Example use:
      * (code)
+     * // unregister a single listener for the "loadstart" event
+     * events.un({"loadstart", loadStartListener});
+     *
+     * // this is equivalent to the following
+     * events.unregister("loadstart", undefined, loadStartListener);
+     *
+     * // unregister multiple listeners with the same `this` object
      * events.un({
      *     "loadstart": loadStartListener,
      *     "loadend": loadEndListener,
      *     scope: object
      * });
+     *
+     * // this is equivalent to the following
+     * events.unregister("loadstart", object, loadStartListener);
+     * events.unregister("loadstart", object, loadEndListener);
      * (end)
      */
     un: function(object) {
@@ -759,10 +786,15 @@
      * evt - {Event} 
      */
     handleBrowserEvent: function (evt) {
+        var type = evt.type, listeners = this.listeners[type];
+        if(!listeners || listeners.length == 0) {
+            // noone's listening, bail out
+            return;
+        }
         if (this.includeXY) {
             evt.xy = this.getMousePosition(evt);
         } 
-        this.triggerEvent(evt.type, evt);
+        this.triggerEvent(type, evt);
     },
 
     /**
@@ -796,11 +828,10 @@
         }
         
         if (!this.element.scrolls) {
+            var viewportElement = OpenLayers.Util.getViewportElement();
             this.element.scrolls = [
-                (document.documentElement.scrollLeft
-                         || document.body.scrollLeft),
-                (document.documentElement.scrollTop
-                         || document.body.scrollTop)
+                viewportElement.scrollLeft,
+                viewportElement.scrollTop
             ];
         }
 
@@ -813,8 +844,6 @@
         
         if (!this.element.offsets) {
             this.element.offsets = OpenLayers.Util.pagePosition(this.element);
-            this.element.offsets[0] += this.element.scrolls[0];
-            this.element.offsets[1] += this.element.scrolls[1];
         }
         return new OpenLayers.Pixel(
             (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Feature/Vector.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Feature/Vector.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Feature/Vector.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 // TRASH THIS
@@ -42,8 +43,8 @@
 
     /** 
      * APIProperty: attributes 
-     * {Object} This object holds arbitrary properties that describe the
-     *     feature.
+     * {Object} This object holds arbitrary, serializable properties that
+     *     describe the feature.
      */
     attributes: null,
 
@@ -67,6 +68,13 @@
      * {Object} 
      */
     style: null,
+
+    /**
+     * APIProperty: url
+     * {String} If this property is set it will be taken into account by
+     *     {<OpenLayers.HTTP>} when upadting or deleting the feature.
+     */
+    url: null,
     
     /**
      * Property: renderIntent
@@ -159,6 +167,27 @@
         }    
         return onScreen;
     },
+
+    /**
+     * Method: getVisibility
+     * Determine whether the feature is displayed or not. It may not displayed
+     *     because:
+     *     - its style display property is set to 'none',
+     *     - it doesn't belong to any layer,
+     *     - the styleMap creates a symbolizer with display property set to 'none'
+     *          for it,
+     *     - the layer which it belongs to is not visible.
+     * 
+     * Returns:
+     * {Boolean} The feature is currently displayed.
+     */
+    getVisibility: function() {
+        return !(this.style && this.style.display == 'none' ||
+                 !this.layer ||
+                 this.layer && this.layer.styleMap &&
+                 this.layer.styleMap.createSymbolizer(this, this.renderIntent).display == 'none' ||
+                 this.layer && !this.layer.getVisibility());
+    },
     
     /**
      * Method: createMarker
@@ -332,6 +361,7 @@
  * graphicOpacity - {Number} Opacity (0-1) for an external graphic.
  * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic.
  * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic.
+ * rotation - {Number} For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point (or any point off center as specified by graphicXOffset and graphicYOffset).
  * graphicZIndex - {Number} The integer z-index value to use in rendering.
  * graphicName - {String} Named graphic to use when rendering points.  Supported values include "circle" (default),
  *     "square", "star", "x", "cross", "triangle".
@@ -349,7 +379,12 @@
  *     alignment. Valid values for horizontal alignment: "l"=left, "c"=center, "r"=right. Valid values for vertical
  *     alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb". The canvas renderer does not
  *     support vertical alignment, it will always use "b".
+ * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label.
+ * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label.
+ * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls.
+ *     Default is false.
  * fontColor - {String} The font color for the label, to be provided like CSS.
+ * fontOpacity - {Number} Opacity (0-1) for the label
  * fontFamily - {String} The font family for the label, to be provided like in CSS.
  * fontSize - {String} The font size for the label, to be provided like in CSS.
  * fontWeight - {String} The font weight for the label, to be provided like in CSS.

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Feature/WFS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Feature/WFS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Feature/WFS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Feature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Feature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Feature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -90,6 +91,10 @@
                 this.layer.map.removePopup(this.popup);
             }
         }
+        // remove the marker from the layer
+        if (this.layer != null && this.marker != null) {
+            this.layer.removeMarker(this.marker);
+        }
 
         this.layer = null;
         this.id = null;

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Filter/Comparison.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Filter/Comparison.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Filter/Comparison.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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/Filter.js
@@ -93,20 +94,23 @@
 
     /**
      * APIMethod: evaluate
-     * Evaluates this filter in a specific context.  Should be implemented by
-     *     subclasses.
+     * Evaluates this filter in a specific context.
      * 
      * Parameters:
-     * context - {Object} Context to use in evaluating the filter.
+     * context - {Object} Context to use in evaluating the filter.  If a vector
+     *     feature is provided, the feature.attributes will be used as context.
      * 
      * Returns:
      * {Boolean} The filter applies.
      */
     evaluate: function(context) {
+        if (context instanceof OpenLayers.Feature.Vector) {
+            context = context.attributes;
+        }
         var result = false;
+        var got = context[this.property];
         switch(this.type) {
             case OpenLayers.Filter.Comparison.EQUAL_TO:
-                var got = context[this.property];
                 var exp = this.value;
                 if(!this.matchCase &&
                    typeof got == "string" && typeof exp == "string") {
@@ -116,7 +120,6 @@
                 }
                 break;
             case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:
-                var got = context[this.property];
                 var exp = this.value;
                 if(!this.matchCase &&
                    typeof got == "string" && typeof exp == "string") {
@@ -126,24 +129,24 @@
                 }
                 break;
             case OpenLayers.Filter.Comparison.LESS_THAN:
-                result = context[this.property] < this.value;
+                result = got < this.value;
                 break;
             case OpenLayers.Filter.Comparison.GREATER_THAN:
-                result = context[this.property] > this.value;
+                result = got > this.value;
                 break;
             case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:
-                result = context[this.property] <= this.value;
+                result = got <= this.value;
                 break;
             case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:
-                result = context[this.property] >= this.value;
+                result = got >= this.value;
                 break;
             case OpenLayers.Filter.Comparison.BETWEEN:
-                result = (context[this.property] >= this.lowerBoundary) &&
-                    (context[this.property] <= this.upperBoundary);
+                result = (got >= this.lowerBoundary) &&
+                    (got <= this.upperBoundary);
                 break;
             case OpenLayers.Filter.Comparison.LIKE:
                 var regexp = new RegExp(this.value, "gi");
-                result = regexp.test(context[this.property]);
+                result = regexp.test(got);
                 break;
         }
         return result;

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Filter/FeatureId.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Filter/FeatureId.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Filter/FeatureId.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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. */
 
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Filter/Logical.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Filter/Logical.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Filter/Logical.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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. */
 
 
 /**
@@ -58,11 +59,12 @@
 
     /**
      * APIMethod: evaluate
-     * Evaluates this filter in a specific context.  Should be implemented by
-     *     subclasses.
+     * Evaluates this filter in a specific context.
      * 
      * Parameters:
-     * context - {Object} Context to use in evaluating the filter.
+     * context - {Object} Context to use in evaluating the filter.  A vector
+     *     feature may also be provided to evaluate feature attributes in 
+     *     comparison filters or geometries in spatial filters.
      * 
      * Returns:
      * {Boolean} The filter applies.

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Filter/Spatial.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Filter/Spatial.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Filter/Spatial.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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/Filter.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Filter.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Filter.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Filter.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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. */
 
 
 /**
@@ -16,7 +17,7 @@
     
     /** 
      * Constructor: OpenLayers.Filter
-     * This is an abstract class.  Create an instance of a filter subclass.
+     * This class represents a generic filter.
      *
      * Parameters:
      * options - {Object} Optional object whose properties will be set on the
@@ -38,11 +39,12 @@
 
     /**
      * APIMethod: evaluate
-     * Evaluates this filter in a specific context.  Should be implemented by
-     *     subclasses.
+     * Evaluates this filter in a specific context.  Instances or subclasses
+     * are supposed to override this method.
      * 
      * Parameters:
-     * context - {Object} Context to use in evaluating the filter.
+     * context - {Object} Context to use in evaluating the filter.  If a vector
+     *     feature is provided, the feature.attributes will be used as context.
      * 
      * Returns:
      * {Boolean} The filter applies.

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML/Features.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML/Features.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML/Features.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2009 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/ArcXML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2009 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -221,7 +222,9 @@
             }
         }
           
-        if (!arcNode) {
+        // in Safari, arcNode will be there but will have a child named 
+        // parsererror
+        if (!arcNode || arcNode.firstChild.nodeName === 'parsererror') {
             var error, source;
             try {
                 error = data.firstChild.nodeValue;
@@ -557,8 +560,8 @@
                         var keys = this.fontStyleKeys;
                         for (var i = 0, len = keys.length; i < len; i++) {
                             var key = keys[i];
-                            if (symbol[key]) {
-                                selem.setAttribute(key, renderer[key]);
+                            if (exact.symbol[key]) {
+                                selem.setAttribute(key, exact.symbol[key]);
                             }
                         }    
                         eelem.appendChild(selem);

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/Atom.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/Atom.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Atom.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Atom.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,727 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Atom
+ * Read/write Atom feeds. Create a new instance with the
+ *     <OpenLayers.Format.AtomFeed> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Atom = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.  Properties
+     *     of this object should not be set individually.  Read-only.  All
+     *     XML subclasses should have their own namespaces object.  Use
+     *     <setNamespace> to add or set a namespace alias after construction.
+     */
+    namespaces: {
+        atom: "http://www.w3.org/2005/Atom",
+        georss: "http://www.georss.org/georss"
+    },
+    
+    /**
+     * APIProperty: feedTitle
+     * {String} Atom feed elements require a title.  Default is "untitled".
+     */
+    feedTitle: "untitled",
+
+    /**
+     * APIProperty: defaultEntryTitle
+     * {String} Atom entry elements require a title.  In cases where one is
+     *     not provided in the feature attributes, this will be used.  Default
+     *     is "untitled".
+     */
+    defaultEntryTitle: "untitled",
+
+    /**
+     * Property: gmlParse
+     * {Object} GML Format object for parsing features
+     * Non-API and only created if necessary
+     */
+    gmlParser: null,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x)
+     * For GeoRSS the default is (y,x), therefore: false
+     */
+    xy: false,
+    
+    /**
+     * Constructor: OpenLayers.Format.AtomEntry
+     * Create a new parser for Atom.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from an Atom feed or entry document.
+     
+     * Parameters:
+     * doc - {Element} or {String}
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(doc) {
+        if (typeof doc == "string") {
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+        return this.parseFeatures(doc);
+    },
+    
+    /**
+     * APIMethod: write
+     * Serialize or more feature nodes to Atom documents.
+     *
+     * Parameters:
+     * features - a single {<OpenLayers.Feature.Vector>} or an
+     * Array({<OpenLayers.Feature.Vector>}).
+     *
+     * Returns:
+     * {String} an Atom entry document if passed one feature node, or a feed
+     * document if passed an array of feature nodes.
+     */
+    write: function(features) {
+        var doc;
+        if (features instanceof Array) {
+            doc = this.createElementNSPlus("atom:feed");
+            doc.appendChild(
+                this.createElementNSPlus("atom:title", {
+                    value: this.feedTitle
+                })
+            );
+            for (var i=0, ii=features.length; i<ii; i++) {
+                doc.appendChild(this.buildEntryNode(features[i]));
+            }
+        }
+        else {
+            doc = this.buildEntryNode(features);
+        }
+        return OpenLayers.Format.XML.prototype.write.apply(this, [doc]);
+    },
+    
+    /**
+     * Method: buildContentNode
+     *
+     * Parameters:
+     * content - {Object}
+     *
+     * Returns:
+     * {DOMElement} an Atom content node.
+     *
+     * TODO: types other than text.
+     */
+    buildContentNode: function(content) {
+        var node = this.createElementNSPlus("atom:content", {
+            attributes: {
+                type: content.type || null
+            }
+        });
+        if (content.src) {
+            node.setAttribute("src", content.src);
+        } else {
+            if (content.type == "text" || content.type == null) {
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            } else if (content.type == "html") {
+                if (typeof content.value != "string") {
+                    throw "HTML content must be in form of an escaped string";
+                }
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            } else if (content.type == "xhtml") {
+                node.appendChild(content.value);
+            } else if (content.type == "xhtml" ||
+                           content.type.match(/(\+|\/)xml$/)) {
+                node.appendChild(content.value);
+            }
+            else { // MUST be a valid Base64 encoding
+                node.appendChild(
+                    this.createTextNode(content.value)
+                );
+            }
+        }
+        return node;
+    },
+    
+    /**
+     * Method: buildEntryNode
+     * Build an Atom entry node from a feature object.
+     *
+     * Parameters:
+     * feature - {<OpenLayers.Feature.Vector>}
+     *
+     * Returns:
+     * {DOMElement} an Atom entry node.
+     *
+     * These entries are geared for publication using AtomPub.
+     *
+     * TODO: support extension elements
+     */
+    buildEntryNode: function(feature) {
+        var attrib = feature.attributes;
+        var atomAttrib = attrib.atom || {};
+        var entryNode = this.createElementNSPlus("atom:entry");
+        
+        // atom:author
+        if (atomAttrib.authors) {
+            var authors = atomAttrib.authors instanceof Array ?
+                atomAttrib.authors : [atomAttrib.authors];
+            for (var i=0, ii=authors.length; i<ii; i++) {
+                entryNode.appendChild(
+                    this.buildPersonConstructNode(
+                        "author", authors[i]
+                    )
+                );
+            }
+        }
+        
+        // atom:category
+        if (atomAttrib.categories) {
+            var categories = atomAttrib.categories instanceof Array ?
+                atomAttrib.categories : [atomAttrib.categories];
+            var category;
+            for (var i=0, ii=categories.length; i<ii; i++) {
+                category = categories[i];
+                entryNode.appendChild(
+                    this.createElementNSPlus("atom:category", {
+                        attributes: {
+                            term: category.term,
+                            scheme: category.scheme || null,
+                            label: category.label || null
+                        }
+                    })
+                );
+            }
+        }
+        
+        // atom:content
+        if (atomAttrib.content) {
+            entryNode.appendChild(this.buildContentNode(atomAttrib.content));
+        }
+        
+        // atom:contributor
+        if (atomAttrib.contributors) {
+            var contributors = atomAttrib.contributors instanceof Array ?
+                atomAttrib.contributors : [atomAttrib.contributors];
+            for (var i=0, ii=contributors.length; i<ii; i++) {
+                entryNode.appendChild(
+                    this.buildPersonConstructNode(
+                        "contributor",
+                        contributors[i]
+                        )
+                    );
+            }
+        }
+        
+        // atom:id
+        if (feature.fid) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:id", {
+                    value: feature.fid
+                })
+            );
+        }
+        
+        // atom:link
+        if (atomAttrib.links) {
+            var links = atomAttrib.links instanceof Array ?
+                atomAttrib.links : [atomAttrib.links];
+            var link;
+            for (var i=0, ii=links.length; i<ii; i++) {
+                link = links[i];
+                entryNode.appendChild(
+                    this.createElementNSPlus("atom:link", {
+                        attributes: {
+                            href: link.href,
+                            rel: link.rel || null,
+                            type: link.type || null,
+                            hreflang: link.hreflang || null,
+                            title: link.title || null,
+                            length: link.length || null
+                        }
+                    })
+                );
+            }
+        }
+        
+        // atom:published
+        if (atomAttrib.published) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:published", {
+                    value: atomAttrib.published
+                })
+            );
+        }
+        
+        // atom:rights
+        if (atomAttrib.rights) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:rights", {
+                    value: atomAttrib.rights
+                })
+            );
+        }
+        
+        // atom:source not implemented
+        
+        // atom:summary
+        if (atomAttrib.summary || attrib.description) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:summary", {
+                    value: atomAttrib.summary || attrib.description
+                })
+            );
+        }
+        
+        // atom:title
+        entryNode.appendChild(
+            this.createElementNSPlus("atom:title", {
+                value: atomAttrib.title || attrib.title || this.defaultEntryTitle
+            })
+        );
+        
+        // atom:updated
+        if (atomAttrib.updated) {
+            entryNode.appendChild(
+                this.createElementNSPlus("atom:updated", {
+                    value: atomAttrib.updated
+                })
+            );
+        }
+        
+        // georss:where
+        if (feature.geometry) {
+            var whereNode = this.createElementNSPlus("georss:where");
+            whereNode.appendChild(
+                this.buildGeometryNode(feature.geometry)
+            );
+            entryNode.appendChild(whereNode);
+        }
+        
+        return entryNode;
+    },
+    
+    /**
+     * Method: initGmlParser
+     * Creates a GML parser.
+     */
+    initGmlParser: function() {
+        this.gmlParser = new OpenLayers.Format.GML.v3({
+            xy: this.xy,
+            featureNS: "http://example.com#feature",
+            internalProjection: this.internalProjection,
+            externalProjection: this.externalProjection
+        });
+    },
+    
+    /**
+     * Method: buildGeometryNode
+     * builds a GeoRSS node with a given geometry
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>}
+     *
+     * Returns:
+     * {DOMElement} A gml node.
+     */
+    buildGeometryNode: function(geometry) {
+        if (!this.gmlParser) {
+            this.initGmlParser();
+        }
+        var node = this.gmlParser.writeNode("feature:_geometry", geometry);
+        return node.firstChild;
+    },
+    
+    /**
+     * Method: buildPersonConstructNode
+     *
+     * Parameters:
+     * name - {String}
+     * value - {Object}
+     *
+     * Returns:
+     * {DOMElement} an Atom person construct node.
+     *
+     * Example:
+     * >>> buildPersonConstructNode("author", {name: "John Smith"})
+     * {<author><name>John Smith</name></author>}
+     *
+     * TODO: how to specify extension elements? Add to the oNames array?
+     */
+    buildPersonConstructNode: function(name, value) {
+        var oNames = ["uri", "email"];
+        var personNode = this.createElementNSPlus("atom:" + name);
+        personNode.appendChild(
+            this.createElementNSPlus("atom:name", {
+                value: value.name
+            })
+        );
+        for (var i=0, ii=oNames.length; i<ii; i++) {
+            if (value[oNames[i]]) {
+                personNode.appendChild(
+                    this.createElementNSPlus("atom:" + oNames[i], {
+                        value: value[oNames[i]]
+                    })
+                );
+            }
+        }
+        return personNode;
+    },
+    
+    /**
+     * Method: getFirstChildValue
+     *
+     * Parameters:
+     * node - {DOMElement}
+     * nsuri - {String} Child node namespace uri ("*" for any).
+     * name - {String} Child node name.
+     * def - {String} Optional string default to return if no child found.
+     *
+     * Returns:
+     * {String} The value of the first child with the given tag name.  Returns
+     *     default value or empty string if none found.
+     */
+    getFirstChildValue: function(node, nsuri, name, def) {
+        var value;
+        var nodes = this.getElementsByTagNameNS(node, nsuri, name);
+        if (nodes && nodes.length > 0) {
+            value = this.getChildValue(nodes[0], def);
+        } else {
+            value = def;
+        }
+        return value;
+    },
+    
+    /**
+     * Method: parseFeature
+     * Parse feature from an Atom entry node..
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An <OpenLayers.Feature.Vector>.
+     */
+    parseFeature: function(node) {
+        var atomAttrib = {};
+        var value = null;
+        var nodes = null;
+        var attval = null;
+        var atomns = this.namespaces.atom;
+        
+        // atomAuthor*
+        this.parsePersonConstructs(node, "author", atomAttrib);
+        
+        // atomCategory*
+        nodes = this.getElementsByTagNameNS(node, atomns, "category");
+        if (nodes.length > 0) {
+            atomAttrib.categories = [];
+        }
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            value = {};
+            value.term = nodes[i].getAttribute("term");
+            attval = nodes[i].getAttribute("scheme");
+            if (attval) { value.scheme = attval; }
+            attval = nodes[i].getAttribute("label");
+            if (attval) { value.label = attval; }
+            atomAttrib.categories.push(value);
+        }
+        
+        // atomContent?
+        nodes = this.getElementsByTagNameNS(node, atomns, "content");
+        if (nodes.length > 0) {
+            value = {};
+            attval = nodes[0].getAttribute("type");
+            if (attval) {
+                value.type = attval;
+            }
+            attval = nodes[0].getAttribute("src");
+            if (attval) {
+                value.src = attval;
+            } else {
+                if (value.type == "text" || 
+                    value.type == "html" || 
+                    value.type == null ) {
+                    value.value = this.getFirstChildValue(
+                                        node,
+                                        atomns,
+                                        "content",
+                                        null
+                                        );
+                } else if (value.type == "xhtml" ||
+                           value.type.match(/(\+|\/)xml$/)) {
+                    value.value = this.getChildEl(nodes[0]);
+                } else { // MUST be base64 encoded
+                    value.value = this.getFirstChildValue(
+                                        node,
+                                        atomns,
+                                        "content",
+                                        null
+                                        );
+                }
+                atomAttrib.content = value;
+            }
+        }
+        
+        // atomContributor*
+        this.parsePersonConstructs(node, "contributor", atomAttrib);
+        
+        // atomId
+        atomAttrib.id = this.getFirstChildValue(node, atomns, "id", null);
+        
+        // atomLink*
+        nodes = this.getElementsByTagNameNS(node, atomns, "link");
+        if (nodes.length > 0) {
+            atomAttrib.links = new Array(nodes.length);
+        }
+        var oAtts = ["rel", "type", "hreflang", "title", "length"];
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            value = {};
+            value.href = nodes[i].getAttribute("href");
+            for (var j=0, jj=oAtts.length; j<jj; j++) {
+                attval = nodes[i].getAttribute(oAtts[j]);
+                if (attval) {
+                    value[oAtts[j]] = attval;
+                }
+            }
+            atomAttrib.links[i] = value;
+        }
+        
+        // atomPublished?
+        value = this.getFirstChildValue(node, atomns, "published", null);
+        if (value) {
+            atomAttrib.published = value;
+        }
+        
+        // atomRights?
+        value = this.getFirstChildValue(node, atomns, "rights", null);
+        if (value) {
+            atomAttrib.rights = value;
+        }
+        
+        // atomSource? -- not implemented
+        
+        // atomSummary?
+        value = this.getFirstChildValue(node, atomns, "summary", null);
+        if (value) {
+            atomAttrib.summary = value;
+        }
+        
+        // atomTitle
+        atomAttrib.title = this.getFirstChildValue(
+                                node, atomns, "title", null
+                                );
+        
+        // atomUpdated
+        atomAttrib.updated = this.getFirstChildValue(
+                                node, atomns, "updated", null
+                                );
+        
+        var featureAttrib = {
+            title: atomAttrib.title,
+            description: atomAttrib.summary,
+            atom: atomAttrib
+        };
+        var geometry = this.parseLocations(node)[0];
+        var feature = new OpenLayers.Feature.Vector(geometry, featureAttrib);
+        feature.fid = atomAttrib.id;
+        return feature;
+    },
+    
+    /**
+     * Method: parseFeatures
+     * Return features from an Atom entry or feed.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s.
+     */
+    parseFeatures: function(node) {
+        var features = [];
+        var entries = this.getElementsByTagNameNS(
+            node, this.namespaces.atom, "entry"
+        );
+        if (entries.length == 0) {
+            entries = [node];
+        }
+        for (var i=0, ii=entries.length; i<ii; i++) {
+            features.push(this.parseFeature(entries[i]));
+        }
+        return features;
+    },
+    
+    /**
+     * Method: parseLocations
+     * Parse the locations from an Atom entry or feed.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     *
+     * Returns:
+     * An Array of <OpenLayers.Geometry>s.
+     */
+    parseLocations: function(node) {
+        var georssns = this.namespaces.georss;
+
+        var locations = {components: []};
+        var where = this.getElementsByTagNameNS(node, georssns, "where");
+        if (where && where.length > 0) {
+            if (!this.gmlParser) {
+                this.initGmlParser();
+            }
+            for (var i=0, ii=where.length; i<ii; i++) {
+                this.gmlParser.readChildNodes(where[i], locations);
+            }
+        }
+        
+        var components = locations.components;
+        var point = this.getElementsByTagNameNS(node, georssns, "point");
+        if (point && point.length > 0) {
+            for (var i=0, ii=point.length; i<ii; i++) {
+                var xy = OpenLayers.String.trim(
+                            point[i].firstChild.nodeValue
+                            ).split(/\s+/);
+                if (xy.length !=2) {
+                    xy = OpenLayers.String.trim(
+                                point[i].firstChild.nodeValue
+                                ).split(/\s*,\s*/);
+                }
+                components.push(
+                    new OpenLayers.Geometry.Point(
+                        parseFloat(xy[1]),
+                        parseFloat(xy[0])
+                    )
+                );
+            }
+        }
+
+        var line = this.getElementsByTagNameNS(node, georssns, "line");
+        if (line && line.length > 0) {
+            var coords;
+            var p;
+            var points;
+            for (var i=0, ii=line.length; i<ii; i++) {
+                coords = OpenLayers.String.trim(
+                                line[i].firstChild.nodeValue
+                                ).split(/\s+/);
+                points = [];
+                for (var j=0, jj=coords.length; j<jj; j+=2) {
+                    p = new OpenLayers.Geometry.Point(
+                        parseFloat(coords[j+1]),
+                        parseFloat(coords[j])
+                    );
+                    points.push(p);
+                }
+                components.push(
+                    new OpenLayers.Geometry.LineString(points)
+                );
+            }
+        }        
+
+        var polygon = this.getElementsByTagNameNS(node, georssns, "polygon");
+        if (polygon && polygon.length > 0) {
+            var coords;
+            var p;
+            var points;
+            for (var i=0, ii=polygon.length; i<ii; i++) {
+                coords = OpenLayers.String.trim(
+                            polygon[i].firstChild.nodeValue
+                            ).split(/\s+/);
+                points = [];
+                for (var j=0, jj=coords.length; j<jj; j+=2) {
+                    p = new OpenLayers.Geometry.Point(
+                        parseFloat(coords[j+1]),
+                        parseFloat(coords[j])
+                    );
+                    points.push(p);
+                }
+                components.push(
+                    new OpenLayers.Geometry.Polygon(
+                        [new OpenLayers.Geometry.LinearRing(components)]
+                    )
+                );
+            }
+        }
+        
+        if (this.internalProjection && this.externalProjection) {
+            for (var i=0, ii=components.length; i<ii; i++) {
+                if (components[i]) {
+                    components[i].transform(
+                        this.externalProjection,
+                        this.internalProjection
+                    );
+                }
+            }
+        }
+        
+        return components;
+    },
+    
+    /**
+     * Method: parsePersonConstruct
+     * Parse Atom person constructs from an Atom entry node.
+     *
+     * Parameters:
+     * node - {DOMElement} An Atom entry or feed node.
+     * name - {String} Construcy name ("author" or "contributor")
+     * data = {Object} Object in which to put parsed persons.
+     *
+     * Returns:
+     * An {Object}.
+     */
+    parsePersonConstructs: function(node, name, data) {
+        var persons = [];
+        var atomns = this.namespaces.atom;
+        var nodes = this.getElementsByTagNameNS(node, atomns, name);
+        var oAtts = ["uri", "email"];
+        for (var i=0, ii=nodes.length; i<ii; i++) {
+            var value = {};
+            value.name = this.getFirstChildValue(
+                            nodes[i],
+                            atomns,
+                            "name",
+                            null
+                            );
+            for (var j=0, jj=oAtts.length; j<jj; j++) {
+                var attval = this.getFirstChildValue(
+                            nodes[i],
+                            atomns,
+                            oAtts[j],
+                            null);
+                if (attval) {
+                    value[oAtts[j]] = attval;
+                }
+            }
+            persons.push(value);
+        }
+        if (persons.length > 0) {
+            data[name + "s"] = persons;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Atom"
+});

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,243 +0,0 @@
-/* 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/Format/XML.js
- * @requires OpenLayers/Format/CSWGetDomain.js
- */
-
-/**
- * Class: OpenLayers.Format.CSWGetDomain.v2_0_2
- *     A format for creating CSWGetDomain v2.0.2 transactions. 
- *     Create a new instance with the
- *     <OpenLayers.Format.CSWGetDomain.v2_0_2> constructor.
- *
- * Inherits from:
- *  - <OpenLayers.Format.XML>
- */
-OpenLayers.Format.CSWGetDomain.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
-    
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        xlink: "http://www.w3.org/1999/xlink",
-        xsi: "http://www.w3.org/2001/XMLSchema-instance",
-        csw: "http://www.opengis.net/cat/csw/2.0.2"
-    },
-
-    /**
-     * Property: defaultPrefix
-     * {String} The default prefix (used by Format.XML).
-     */
-    defaultPrefix: "csw",
-    
-    /**
-     * Property: version
-     * {String} CSW version number.
-     */
-    version: "2.0.2",
-    
-    /**
-     * Property: schemaLocation
-     * {String} http://www.opengis.net/cat/csw/2.0.2
-     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
-     */
-    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
-
-    /**
-     * APIProperty: PropertyName
-     * {String} Value of the csw:PropertyName element, used when
-     *     writing a GetDomain document.
-     */
-    PropertyName: null,
-
-    /**
-     * APIProperty: ParameterName
-     * {String} Value of the csw:ParameterName element, used when
-     *     writing a GetDomain document.
-     */
-    ParameterName: null,
-    
-    /**
-     * Constructor: OpenLayers.Format.CSWGetDomain.v2_0_2
-     * A class for parsing and generating CSWGetDomain v2.0.2 transactions.
-     *
-     * Parameters:
-     * options - {Object} Optional object whose properties will be set on the
-     *     instance.
-     *
-     * Valid options properties:
-     * - PropertyName
-     * - ParameterName
-     */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-    },
-
-    /**
-     * APIMethod: read
-     * Parse the response from a GetDomain request.
-     */
-    read: function(data) {
-        if(typeof data == "string") { 
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        if(data && data.nodeType == 9) {
-            data = data.documentElement;
-        }
-        var obj = {};
-        this.readNode(data, obj);
-        return obj;
-    },
-    
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "csw": {
-            "GetDomainResponse": function(node, obj) {
-                this.readChildNodes(node, obj);
-            },
-            "DomainValues": function(node, obj) {
-                if (!(obj.DomainValues instanceof Array)) {
-                    obj.DomainValues = [];
-                }
-                var attrs = node.attributes;
-                var domainValue = {};
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    domainValue[attrs[i].name] = attrs[i].nodeValue;
-                }
-                this.readChildNodes(node, domainValue);
-                obj.DomainValues.push(domainValue);
-            },
-            "PropertyName": function(node, obj) {
-                obj.PropertyName = this.getChildValue(node);
-            },
-            "ParameterName": function(node, obj) {
-                obj.ParameterName = this.getChildValue(node);
-            },
-            "ListOfValues": function(node, obj) {
-                if (!(obj.ListOfValues instanceof Array)) {
-                    obj.ListOfValues = [];
-                }
-                this.readChildNodes(node, obj.ListOfValues);
-            },
-            "Value": function(node, obj) {
-                var attrs = node.attributes;
-                var value = {}
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    value[attrs[i].name] = attrs[i].nodeValue;
-                }
-                value.value = this.getChildValue(node);
-                obj.push({Value: value});
-            },
-            "ConceptualScheme": function(node, obj) {
-                obj.ConceptualScheme = {};
-                this.readChildNodes(node, obj.ConceptualScheme);
-            },
-            "Name": function(node, obj) {
-                obj.Name = this.getChildValue(node);
-            },
-            "Document": function(node, obj) {
-                obj.Document = this.getChildValue(node);
-            },
-            "Authority": function(node, obj) {
-                obj.Authority = this.getChildValue(node);
-            },
-            "RangeOfValues": function(node, obj) {
-                obj.RangeOfValues = {};
-                this.readChildNodes(node, obj.RangeOfValues);
-            },
-            "MinValue": function(node, obj) {
-                var attrs = node.attributes;
-                var value = {}
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    value[attrs[i].name] = attrs[i].nodeValue;
-                }
-                value.value = this.getChildValue(node);
-                obj.MinValue = value;
-            },
-            "MaxValue": function(node, obj) {
-                var attrs = node.attributes;
-                var value = {}
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    value[attrs[i].name] = attrs[i].nodeValue;
-                }
-                value.value = this.getChildValue(node);
-                obj.MaxValue = value;
-            }
-        }
-    },
-    
-    /**
-     * APIMethod: write
-     * Given an configuration js object, write a CSWGetDomain request. 
-     *
-     * Parameters:
-     * options - {Object} A object mapping the request.
-     *
-     * Returns:
-     * {String} A serialized CSWGetDomain request.
-     */
-    write: function(options) {
-        var node = this.writeNode("csw:GetDomain", options);
-        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
-    },
-
-    /**
-     * Property: writers
-     * As a compliment to the readers property, this structure contains public
-     *     writing functions grouped by namespace alias and named like the
-     *     node names they produce.
-     */
-    writers: {
-        "csw": {
-            "GetDomain": function(options) {
-                var node = this.createElementNSPlus("csw:GetDomain", {
-                    attributes: {
-                        service: "CSW",
-                        version: this.version
-                    }
-                });
-                if (options.PropertyName || this.PropertyName) {
-                    this.writeNode(
-                        "csw:PropertyName",
-                        options.PropertyName || this.PropertyName,
-                        node
-                    );
-                } else if (options.ParameterName || this.ParameterName) {
-                    this.writeNode(
-                        "csw:ParameterName",
-                        options.ParameterName || this.ParameterName,
-                        node
-                    );
-                }
-                this.readChildNodes(node, options);
-                return node;
-            },
-            "PropertyName": function(value) {
-                var node = this.createElementNSPlus("csw:PropertyName", {
-                    value: value
-                });
-                return node;
-            },
-            "ParameterName": function(value) {
-                var node = this.createElementNSPlus("csw:ParameterName", {
-                    value: value
-                });
-                return node;
-            }
-        }
-    },
-   
-    CLASS_NAME: "OpenLayers.Format.CSWGetDomain.v2_0_2" 
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,243 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetDomain.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetDomain.v2_0_2
+ *     A format for creating CSWGetDomain v2.0.2 transactions. 
+ *     Create a new instance with the
+ *     <OpenLayers.Format.CSWGetDomain.v2_0_2> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetDomain.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance",
+        csw: "http://www.opengis.net/cat/csw/2.0.2"
+    },
+
+    /**
+     * Property: defaultPrefix
+     * {String} The default prefix (used by Format.XML).
+     */
+    defaultPrefix: "csw",
+    
+    /**
+     * Property: version
+     * {String} CSW version number.
+     */
+    version: "2.0.2",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/cat/csw/2.0.2
+     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+     */
+    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+    /**
+     * APIProperty: PropertyName
+     * {String} Value of the csw:PropertyName element, used when
+     *     writing a GetDomain document.
+     */
+    PropertyName: null,
+
+    /**
+     * APIProperty: ParameterName
+     * {String} Value of the csw:ParameterName element, used when
+     *     writing a GetDomain document.
+     */
+    ParameterName: null,
+    
+    /**
+     * Constructor: OpenLayers.Format.CSWGetDomain.v2_0_2
+     * A class for parsing and generating CSWGetDomain v2.0.2 transactions.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties:
+     * - PropertyName
+     * - ParameterName
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Parse the response from a GetDomain request.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var obj = {};
+        this.readNode(data, obj);
+        return obj;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "csw": {
+            "GetDomainResponse": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "DomainValues": function(node, obj) {
+                if (!(obj.DomainValues instanceof Array)) {
+                    obj.DomainValues = [];
+                }
+                var attrs = node.attributes;
+                var domainValue = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    domainValue[attrs[i].name] = attrs[i].nodeValue;
+                }
+                this.readChildNodes(node, domainValue);
+                obj.DomainValues.push(domainValue);
+            },
+            "PropertyName": function(node, obj) {
+                obj.PropertyName = this.getChildValue(node);
+            },
+            "ParameterName": function(node, obj) {
+                obj.ParameterName = this.getChildValue(node);
+            },
+            "ListOfValues": function(node, obj) {
+                if (!(obj.ListOfValues instanceof Array)) {
+                    obj.ListOfValues = [];
+                }
+                this.readChildNodes(node, obj.ListOfValues);
+            },
+            "Value": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {}
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.push({Value: value});
+            },
+            "ConceptualScheme": function(node, obj) {
+                obj.ConceptualScheme = {};
+                this.readChildNodes(node, obj.ConceptualScheme);
+            },
+            "Name": function(node, obj) {
+                obj.Name = this.getChildValue(node);
+            },
+            "Document": function(node, obj) {
+                obj.Document = this.getChildValue(node);
+            },
+            "Authority": function(node, obj) {
+                obj.Authority = this.getChildValue(node);
+            },
+            "RangeOfValues": function(node, obj) {
+                obj.RangeOfValues = {};
+                this.readChildNodes(node, obj.RangeOfValues);
+            },
+            "MinValue": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {}
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.MinValue = value;
+            },
+            "MaxValue": function(node, obj) {
+                var attrs = node.attributes;
+                var value = {}
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    value[attrs[i].name] = attrs[i].nodeValue;
+                }
+                value.value = this.getChildValue(node);
+                obj.MaxValue = value;
+            }
+        }
+    },
+    
+    /**
+     * APIMethod: write
+     * Given an configuration js object, write a CSWGetDomain request. 
+     *
+     * Parameters:
+     * options - {Object} A object mapping the request.
+     *
+     * Returns:
+     * {String} A serialized CSWGetDomain request.
+     */
+    write: function(options) {
+        var node = this.writeNode("csw:GetDomain", options);
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "csw": {
+            "GetDomain": function(options) {
+                var node = this.createElementNSPlus("csw:GetDomain", {
+                    attributes: {
+                        service: "CSW",
+                        version: this.version
+                    }
+                });
+                if (options.PropertyName || this.PropertyName) {
+                    this.writeNode(
+                        "csw:PropertyName",
+                        options.PropertyName || this.PropertyName,
+                        node
+                    );
+                } else if (options.ParameterName || this.ParameterName) {
+                    this.writeNode(
+                        "csw:ParameterName",
+                        options.ParameterName || this.ParameterName,
+                        node
+                    );
+                }
+                this.readChildNodes(node, options);
+                return node;
+            },
+            "PropertyName": function(value) {
+                var node = this.createElementNSPlus("csw:PropertyName", {
+                    value: value
+                });
+                return node;
+            },
+            "ParameterName": function(value) {
+                var node = this.createElementNSPlus("csw:ParameterName", {
+                    value: value
+                });
+                return node;
+            }
+        }
+    },
+   
+    CLASS_NAME: "OpenLayers.Format.CSWGetDomain.v2_0_2" 
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/CSWGetDomain.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetDomain.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,34 @@
+/* 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/Format.js
+ */
+
+/**
+ * Function: OpenLayers.Format.CSWGetDomain.
+ *     Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetDomain format of the given version.
+ */
+OpenLayers.Format.CSWGetDomain = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Format.CSWGetDomain.DEFAULTS
+    );
+    var cls = OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported CSWGetDomain version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Format.CSWGetDomain.DEFAULTS
+ * {Object} Default properties for the CSWGetDomain format.
+ */
+OpenLayers.Format.CSWGetDomain.DEFAULTS = {
+    "version": "2.0.2"
+};

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,440 +0,0 @@
-/* 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/Format/XML.js
- * @requires OpenLayers/Format/CSWGetRecords.js
- * @requires OpenLayers/Format/Filter/v1_0_0.js
- * @requires OpenLayers/Format/Filter/v1_1_0.js
- * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
- */
-
-/**
- * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
- *     A format for creating CSWGetRecords v2.0.2 transactions. 
- *     Create a new instance with the
- *     <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
- *
- * Inherits from:
- *  - <OpenLayers.Format.XML>
- */
-OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
-    
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        xlink: "http://www.w3.org/1999/xlink",
-        xsi: "http://www.w3.org/2001/XMLSchema-instance",
-        csw: "http://www.opengis.net/cat/csw/2.0.2",
-        dc: "http://purl.org/dc/elements/1.1/",
-        dct: "http://purl.org/dc/terms/",
-        ows: "http://www.opengis.net/ows"
-    },
-    
-    /**
-     * Property: defaultPrefix
-     * {String} The default prefix (used by Format.XML).
-     */
-    defaultPrefix: "csw",
-    
-    /**
-     * Property: version
-     * {String} CSW version number.
-     */
-    version: "2.0.2",
-    
-    /**
-     * Property: schemaLocation
-     * {String} http://www.opengis.net/cat/csw/2.0.2
-     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
-     */
-    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
-
-    /**
-     * APIProperty: requestId
-     * {String} Value of the requestId attribute of the GetRecords element.
-     */
-    requestId: null,
-
-    /**
-     * APIProperty: resultType
-     * {String} Value of the resultType attribute of the GetRecords element,
-     *     specifies the result type in the GetRecords response, "hits" is
-     *     the default.
-     */
-    resultType: null,
-
-    /**
-     * APIProperty: outputFormat
-     * {String} Value of the outputFormat attribute of the GetRecords element,
-     *     specifies the format of the GetRecords response,
-     *     "application/xml" is the default.
-     */
-    outputFormat: null,
-
-    /**
-     * APIProperty: outputSchema
-     * {String} Value of the outputSchema attribute of the GetRecords element,
-     *     specifies the schema of the GetRecords response.
-     */
-    outputSchema: null,
-
-    /**
-     * APIProperty: startPosition
-     * {String} Value of the startPosition attribute of the GetRecords element,
-     *     specifies the start position (offset+1) for the GetRecords response,
-     *     1 is the default.
-     */
-    startPosition: null,
-
-    /**
-     * APIProperty: maxRecords
-     * {String} Value of the maxRecords attribute of the GetRecords element,
-     *     specifies the maximum number of records in the GetRecords response,
-     *     10 is the default.
-     */
-    maxRecords: null,
-
-    /**
-     * APIProperty: DistributedSearch
-     * {String} Value of the csw:DistributedSearch element, used when writing
-     *     a csw:GetRecords document.
-     */
-    DistributedSearch: null,
-
-    /**
-     * APIProperty: ResponseHandler
-     * {Array({String})} Values of the csw:ResponseHandler elements, used when
-     *     writting a csw:GetRecords document.
-     */
-    ResponseHandler: null,
-
-    /**
-     * APIProperty: Query
-     * {String} Value of the csw:Query element, used when writing a csw:GetRecords
-     *     document.
-     */
-    Query: null,
-
-    /**
-     * Property: regExes
-     * Compiled regular expressions for manipulating strings.
-     */
-    regExes: {
-        trimSpace: (/^\s*|\s*$/g),
-        removeSpace: (/\s*/g),
-        splitSpace: (/\s+/),
-        trimComma: (/\s*,\s*/g)
-    },
-
-    /**
-     * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
-     * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
-     *
-     * Parameters:
-     * options - {Object} Optional object whose properties will be set on the
-     *     instance.
-     *
-     * Valid options properties (documented as class properties):
-     * - requestId
-     * - resultType
-     * - outputFormat
-     * - outputSchema
-     * - startPosition
-     * - maxRecords
-     * - DistributedSearch
-     * - ResponseHandler
-     * - Query
-     */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-    },
-
-    /**
-     * APIMethod: read
-     * Parse the response from a GetRecords request.
-     */
-    read: function(data) {
-        if(typeof data == "string") { 
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        if(data && data.nodeType == 9) {
-            data = data.documentElement;
-        }
-        var obj = {};
-        this.readNode(data, obj);
-        return obj;
-    },
-    
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "csw": {
-            "GetRecordsResponse": function(node, obj) {
-                obj.records = [];
-                this.readChildNodes(node, obj);
-                var version = this.getAttributeNS(node, "", 'version');
-                if (version != "") {
-                    obj.version = version;
-                }
-            },
-            "RequestId": function(node, obj) {
-                obj.RequestId = this.getChildValue(node);
-            },
-            "SearchStatus": function(node, obj) {
-                obj.SearchStatus = {};
-                var timestamp = this.getAttributeNS(node, "", 'timestamp');
-                if (timestamp != "") {
-                    obj.SearchStatus.timestamp = timestamp;
-                }
-            },
-            "SearchResults": function(node, obj) {
-                this.readChildNodes(node, obj);
-                var attrs = node.attributes;
-                var SearchResults = {};
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    if ((attrs[i].name == "numberOfRecordsMatched") ||
-                        (attrs[i].name == "numberOfRecordsReturned") ||
-                        (attrs[i].name == "nextRecord")) {
-                        SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
-                    } else {
-                        SearchResults[attrs[i].name] = attrs[i].nodeValue;
-                    }
-                }
-                obj.SearchResults = SearchResults;
-            },
-            "SummaryRecord": function(node, obj) {
-                var record = {type: "SummaryRecord"};
-                this.readChildNodes(node, record);
-                obj.records.push(record);
-            },
-            "BriefRecord": function(node, obj) {
-                var record = {type: "BriefRecord"};
-                this.readChildNodes(node, record);
-                obj.records.push(record);
-            },
-            "DCMIRecord": function(node, obj) {
-                var record = {type: "DCMIRecord"};
-                this.readChildNodes(node, record);
-                obj.records.push(record);
-            },
-            "Record": function(node, obj) {
-                var record = {type: "Record"};
-                this.readChildNodes(node, record);
-                obj.records.push(record);
-            }
-        },
-        "dc": {
-            // audience, contributor, coverage, creator, date, description, format,
-            // identifier, language, provenance, publisher, relation, rights,
-            // rightsHolder, source, subject, title, type, URI
-            "*": function(node, obj) {
-                var name = node.localName || node.nodeName.split(":").pop();
-                if (!(obj[name] instanceof Array)) {
-                    obj[name] = new Array();
-                }
-                var dc_element = {};
-                var attrs = node.attributes;
-                for(var i=0, len=attrs.length; i<len; ++i) {
-                    dc_element[attrs[i].name] = attrs[i].nodeValue;
-                }
-                dc_element.value = this.getChildValue(node);
-                obj[name].push(dc_element);
-            }
-        },
-        "dct": {
-            // abstract, modified, spatial
-            "*": function(node, obj) {
-                var name = node.localName || node.nodeName.split(":").pop();
-                if (!(obj[name] instanceof Array)) {
-                    obj[name] = new Array();
-                }
-                obj[name].push(this.getChildValue(node));
-            }
-        },
-        "ows": OpenLayers.Util.applyDefaults({
-            "BoundingBox": function(node, obj) {
-                if (obj.bounds) {
-                    obj.BoundingBox = [{crs: obj.projection, value: 
-                        [
-                            obj.bounds.left, 
-                            obj.bounds.bottom, 
-                            obj.bounds.right, 
-                            obj.bounds.top
-                    ]
-                    }];
-                    delete obj.projection;
-                    delete obj.bounds;
-                }
-                OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
-                    this, arguments);
-            }
-        }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
-    },
-    
-    /**
-     * Method: write
-     * Given an configuration js object, write a CSWGetRecords request. 
-     *
-     * Parameters:
-     * options - {Object} A object mapping the request.
-     *
-     * Returns:
-     * {String} A serialized CSWGetRecords request.
-     */
-    write: function(options) {
-        var node = this.writeNode("csw:GetRecords", options);
-        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
-    },
-
-    /**
-     * Property: writers
-     * As a compliment to the readers property, this structure contains public
-     *     writing functions grouped by namespace alias and named like the
-     *     node names they produce.
-     */
-    writers: {
-        "csw": {
-            "GetRecords": function(options) {
-                if (!options) {
-                    options = {};
-                }
-                var node = this.createElementNSPlus("csw:GetRecords", {
-                    attributes: {
-                        service: "CSW",
-                        version: this.version,
-                        requestId: options.requestId || this.requestId,
-                        resultType: options.resultType || this.resultType,
-                        outputFormat: options.outputFormat || this.outputFormat,
-                        outputSchema: options.outputSchema || this.outputSchema,
-                        startPosition: options.startPosition || this.startPosition,
-                        maxRecords: options.maxRecords || this.maxRecords
-                    }
-                });
-                if (options.DistributedSearch || this.DistributedSearch) {
-                    this.writeNode(
-                        "csw:DistributedSearch",
-                        options.DistributedSearch || this.DistributedSearch,
-                        node
-                    );
-                }
-                var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
-                if (ResponseHandler instanceof Array && ResponseHandler.length > 0) {
-                    // ResponseHandler must be a non-empty array
-                    for(var i=0, len=ResponseHandler.length; i<len; i++) {
-                        this.writeNode(
-                            "csw:ResponseHandler",
-                            ResponseHandler[i],
-                            node
-                        );
-                    }
-                }
-                this.writeNode("Query", options.Query || this.Query, node);
-                return node;
-            },
-            "DistributedSearch": function(options) {
-                var node = this.createElementNSPlus("csw:DistributedSearch", {
-                    attributes: {
-                        hopCount: options.hopCount
-                    }
-                });
-                return node;
-            },
-            "ResponseHandler": function(options) {
-                var node = this.createElementNSPlus("csw:ResponseHandler", {
-                    value: options.value
-                });
-                return node;
-            },
-            "Query": function(options) {
-                if (!options) {
-                    options = {};
-                }
-                var node = this.createElementNSPlus("csw:Query", {
-                    attributes: {
-                        typeNames: options.typeNames || "csw:Record"
-                    }
-                });
-                var ElementName = options.ElementName;
-                if (ElementName instanceof Array && ElementName.length > 0) {
-                    // ElementName must be a non-empty array
-                    for(var i=0, len=ElementName.length; i<len; i++) {
-                        this.writeNode(
-                            "csw:ElementName",
-                            ElementName[i],
-                            node
-                        );
-                    }
-                } else {
-                    this.writeNode(
-                        "csw:ElementSetName",
-                        options.ElementSetName || {value: 'summary'},
-                        node
-                    );
-                }
-                if (options.Constraint) {
-                    this.writeNode(
-                        "csw:Constraint",
-                        options.Constraint,
-                        node
-                    );
-                }
-                //TODO: not implemented in ogc filters?
-                //if (options.SortBy) {
-                    //this.writeNode(
-                        //"ogc:SortBy",
-                        //options.SortBy,
-                        //node
-                    //);
-                //}
-                return node;
-            },
-            "ElementName": function(options) {
-                var node = this.createElementNSPlus("csw:ElementName", {
-                    value: options.value
-                });
-                return node;
-            },
-            "ElementSetName": function(options) {
-                var node = this.createElementNSPlus("csw:ElementSetName", {
-                    attributes: {
-                        typeNames: options.typeNames
-                    },
-                    value: options.value
-                });
-                return node;
-            },
-            "Constraint": function(options) {
-                var node = this.createElementNSPlus("csw:Constraint", {
-                    attributes: {
-                        version: options.version
-                    }
-                });
-                if (options.Filter) {
-                    var format = new OpenLayers.Format.Filter({
-                        version: options.version
-                    });
-                    node.appendChild(format.write(options.Filter));
-                } else if (options.CqlText) {
-                    var child = this.createElementNSPlus("CqlText", {
-                        value: options.CqlText.value
-                    });
-                    node.appendChild(child);
-                }
-                return node;
-            }
-        }
-    },
-   
-    CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2" 
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,440 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetRecords.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
+ *     A format for creating CSWGetRecords v2.0.2 transactions. 
+ *     Create a new instance with the
+ *     <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance",
+        csw: "http://www.opengis.net/cat/csw/2.0.2",
+        dc: "http://purl.org/dc/elements/1.1/",
+        dct: "http://purl.org/dc/terms/",
+        ows: "http://www.opengis.net/ows"
+    },
+    
+    /**
+     * Property: defaultPrefix
+     * {String} The default prefix (used by Format.XML).
+     */
+    defaultPrefix: "csw",
+    
+    /**
+     * Property: version
+     * {String} CSW version number.
+     */
+    version: "2.0.2",
+    
+    /**
+     * Property: schemaLocation
+     * {String} http://www.opengis.net/cat/csw/2.0.2
+     *   http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+     */
+    schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+    /**
+     * APIProperty: requestId
+     * {String} Value of the requestId attribute of the GetRecords element.
+     */
+    requestId: null,
+
+    /**
+     * APIProperty: resultType
+     * {String} Value of the resultType attribute of the GetRecords element,
+     *     specifies the result type in the GetRecords response, "hits" is
+     *     the default.
+     */
+    resultType: null,
+
+    /**
+     * APIProperty: outputFormat
+     * {String} Value of the outputFormat attribute of the GetRecords element,
+     *     specifies the format of the GetRecords response,
+     *     "application/xml" is the default.
+     */
+    outputFormat: null,
+
+    /**
+     * APIProperty: outputSchema
+     * {String} Value of the outputSchema attribute of the GetRecords element,
+     *     specifies the schema of the GetRecords response.
+     */
+    outputSchema: null,
+
+    /**
+     * APIProperty: startPosition
+     * {String} Value of the startPosition attribute of the GetRecords element,
+     *     specifies the start position (offset+1) for the GetRecords response,
+     *     1 is the default.
+     */
+    startPosition: null,
+
+    /**
+     * APIProperty: maxRecords
+     * {String} Value of the maxRecords attribute of the GetRecords element,
+     *     specifies the maximum number of records in the GetRecords response,
+     *     10 is the default.
+     */
+    maxRecords: null,
+
+    /**
+     * APIProperty: DistributedSearch
+     * {String} Value of the csw:DistributedSearch element, used when writing
+     *     a csw:GetRecords document.
+     */
+    DistributedSearch: null,
+
+    /**
+     * APIProperty: ResponseHandler
+     * {Array({String})} Values of the csw:ResponseHandler elements, used when
+     *     writting a csw:GetRecords document.
+     */
+    ResponseHandler: null,
+
+    /**
+     * APIProperty: Query
+     * {String} Value of the csw:Query element, used when writing a csw:GetRecords
+     *     document.
+     */
+    Query: null,
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
+     * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     *
+     * Valid options properties (documented as class properties):
+     * - requestId
+     * - resultType
+     * - outputFormat
+     * - outputSchema
+     * - startPosition
+     * - maxRecords
+     * - DistributedSearch
+     * - ResponseHandler
+     * - Query
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Parse the response from a GetRecords request.
+     */
+    read: function(data) {
+        if(typeof data == "string") { 
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var obj = {};
+        this.readNode(data, obj);
+        return obj;
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "csw": {
+            "GetRecordsResponse": function(node, obj) {
+                obj.records = [];
+                this.readChildNodes(node, obj);
+                var version = this.getAttributeNS(node, "", 'version');
+                if (version != "") {
+                    obj.version = version;
+                }
+            },
+            "RequestId": function(node, obj) {
+                obj.RequestId = this.getChildValue(node);
+            },
+            "SearchStatus": function(node, obj) {
+                obj.SearchStatus = {};
+                var timestamp = this.getAttributeNS(node, "", 'timestamp');
+                if (timestamp != "") {
+                    obj.SearchStatus.timestamp = timestamp;
+                }
+            },
+            "SearchResults": function(node, obj) {
+                this.readChildNodes(node, obj);
+                var attrs = node.attributes;
+                var SearchResults = {};
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    if ((attrs[i].name == "numberOfRecordsMatched") ||
+                        (attrs[i].name == "numberOfRecordsReturned") ||
+                        (attrs[i].name == "nextRecord")) {
+                        SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
+                    } else {
+                        SearchResults[attrs[i].name] = attrs[i].nodeValue;
+                    }
+                }
+                obj.SearchResults = SearchResults;
+            },
+            "SummaryRecord": function(node, obj) {
+                var record = {type: "SummaryRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "BriefRecord": function(node, obj) {
+                var record = {type: "BriefRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "DCMIRecord": function(node, obj) {
+                var record = {type: "DCMIRecord"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            },
+            "Record": function(node, obj) {
+                var record = {type: "Record"};
+                this.readChildNodes(node, record);
+                obj.records.push(record);
+            }
+        },
+        "dc": {
+            // audience, contributor, coverage, creator, date, description, format,
+            // identifier, language, provenance, publisher, relation, rights,
+            // rightsHolder, source, subject, title, type, URI
+            "*": function(node, obj) {
+                var name = node.localName || node.nodeName.split(":").pop();
+                if (!(obj[name] instanceof Array)) {
+                    obj[name] = new Array();
+                }
+                var dc_element = {};
+                var attrs = node.attributes;
+                for(var i=0, len=attrs.length; i<len; ++i) {
+                    dc_element[attrs[i].name] = attrs[i].nodeValue;
+                }
+                dc_element.value = this.getChildValue(node);
+                obj[name].push(dc_element);
+            }
+        },
+        "dct": {
+            // abstract, modified, spatial
+            "*": function(node, obj) {
+                var name = node.localName || node.nodeName.split(":").pop();
+                if (!(obj[name] instanceof Array)) {
+                    obj[name] = new Array();
+                }
+                obj[name].push(this.getChildValue(node));
+            }
+        },
+        "ows": OpenLayers.Util.applyDefaults({
+            "BoundingBox": function(node, obj) {
+                if (obj.bounds) {
+                    obj.BoundingBox = [{crs: obj.projection, value: 
+                        [
+                            obj.bounds.left, 
+                            obj.bounds.bottom, 
+                            obj.bounds.right, 
+                            obj.bounds.top
+                    ]
+                    }];
+                    delete obj.projection;
+                    delete obj.bounds;
+                }
+                OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
+                    this, arguments);
+            }
+        }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
+    },
+    
+    /**
+     * Method: write
+     * Given an configuration js object, write a CSWGetRecords request. 
+     *
+     * Parameters:
+     * options - {Object} A object mapping the request.
+     *
+     * Returns:
+     * {String} A serialized CSWGetRecords request.
+     */
+    write: function(options) {
+        var node = this.writeNode("csw:GetRecords", options);
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "csw": {
+            "GetRecords": function(options) {
+                if (!options) {
+                    options = {};
+                }
+                var node = this.createElementNSPlus("csw:GetRecords", {
+                    attributes: {
+                        service: "CSW",
+                        version: this.version,
+                        requestId: options.requestId || this.requestId,
+                        resultType: options.resultType || this.resultType,
+                        outputFormat: options.outputFormat || this.outputFormat,
+                        outputSchema: options.outputSchema || this.outputSchema,
+                        startPosition: options.startPosition || this.startPosition,
+                        maxRecords: options.maxRecords || this.maxRecords
+                    }
+                });
+                if (options.DistributedSearch || this.DistributedSearch) {
+                    this.writeNode(
+                        "csw:DistributedSearch",
+                        options.DistributedSearch || this.DistributedSearch,
+                        node
+                    );
+                }
+                var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
+                if (ResponseHandler instanceof Array && ResponseHandler.length > 0) {
+                    // ResponseHandler must be a non-empty array
+                    for(var i=0, len=ResponseHandler.length; i<len; i++) {
+                        this.writeNode(
+                            "csw:ResponseHandler",
+                            ResponseHandler[i],
+                            node
+                        );
+                    }
+                }
+                this.writeNode("Query", options.Query || this.Query, node);
+                return node;
+            },
+            "DistributedSearch": function(options) {
+                var node = this.createElementNSPlus("csw:DistributedSearch", {
+                    attributes: {
+                        hopCount: options.hopCount
+                    }
+                });
+                return node;
+            },
+            "ResponseHandler": function(options) {
+                var node = this.createElementNSPlus("csw:ResponseHandler", {
+                    value: options.value
+                });
+                return node;
+            },
+            "Query": function(options) {
+                if (!options) {
+                    options = {};
+                }
+                var node = this.createElementNSPlus("csw:Query", {
+                    attributes: {
+                        typeNames: options.typeNames || "csw:Record"
+                    }
+                });
+                var ElementName = options.ElementName;
+                if (ElementName instanceof Array && ElementName.length > 0) {
+                    // ElementName must be a non-empty array
+                    for(var i=0, len=ElementName.length; i<len; i++) {
+                        this.writeNode(
+                            "csw:ElementName",
+                            ElementName[i],
+                            node
+                        );
+                    }
+                } else {
+                    this.writeNode(
+                        "csw:ElementSetName",
+                        options.ElementSetName || {value: 'summary'},
+                        node
+                    );
+                }
+                if (options.Constraint) {
+                    this.writeNode(
+                        "csw:Constraint",
+                        options.Constraint,
+                        node
+                    );
+                }
+                //TODO: not implemented in ogc filters?
+                //if (options.SortBy) {
+                    //this.writeNode(
+                        //"ogc:SortBy",
+                        //options.SortBy,
+                        //node
+                    //);
+                //}
+                return node;
+            },
+            "ElementName": function(options) {
+                var node = this.createElementNSPlus("csw:ElementName", {
+                    value: options.value
+                });
+                return node;
+            },
+            "ElementSetName": function(options) {
+                var node = this.createElementNSPlus("csw:ElementSetName", {
+                    attributes: {
+                        typeNames: options.typeNames
+                    },
+                    value: options.value
+                });
+                return node;
+            },
+            "Constraint": function(options) {
+                var node = this.createElementNSPlus("csw:Constraint", {
+                    attributes: {
+                        version: options.version
+                    }
+                });
+                if (options.Filter) {
+                    var format = new OpenLayers.Format.Filter({
+                        version: options.version
+                    });
+                    node.appendChild(format.write(options.Filter));
+                } else if (options.CqlText) {
+                    var child = this.createElementNSPlus("CqlText", {
+                        value: options.CqlText.value
+                    });
+                    node.appendChild(child);
+                }
+                return node;
+            }
+        }
+    },
+   
+    CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2" 
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/CSWGetRecords.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/CSWGetRecords.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,34 @@
+/* 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/Format.js
+ */
+
+/**
+ * Function: OpenLayers.Format.CSWGetRecords.
+ *     Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetRecords format of the given version.
+ */
+OpenLayers.Format.CSWGetRecords = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Format.CSWGetRecords.DEFAULTS
+    );
+    var cls = OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported CSWGetRecords version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Format.CSWGetRecords.DEFAULTS
+ * {Object} Default properties for the CSWGetRecords format.
+ */
+OpenLayers.Format.CSWGetRecords.DEFAULTS = {
+    "version": "2.0.2"
+};

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/Context.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/Context.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Context.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Context.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,334 @@
+/* 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/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Context
+ * Base class for both Format.WMC and Format.OWSContext
+ */
+OpenLayers.Format.Context = OpenLayers.Class({
+
+    /**
+     * APIProperty: version
+     * {String} Specify a version string if one is known.
+     */
+    version: null,
+
+    /**
+     * Property: layerOptions
+     * {Object} Default options for layers created by the parser. These
+     *     options are overridden by the options which are read from the
+     *     capabilities document.
+     */
+    layerOptions: null,
+
+    /**
+     * Property: layerParams
+     * {Object} Default parameters for layers created by the parser. This
+     *     can be used e.g. to override DEFAULT_PARAMS for 
+     *     OpenLayers.Layer.WMS.
+     */
+    layerParams: null,
+
+    /**
+     * Property: parser
+     * {Object} Instance of the versioned parser.  Cached for multiple read and
+     *     write calls of the same version.
+     */
+    parser: null,
+
+    /**
+     * Constructor: OpenLayers.Format.Context
+     * Create a new parser for Context documents.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Util.extend(this, options);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read Context data from a string, and return an object with map
+     *     properties and a list of layers.
+     *
+     * Parameters:
+     * data - {String} or {DOMElement} data to read/parse.
+     * options - {Object} The options object must contain a map property.  If
+     *     the map property is a string, it must be the id of a dom element
+     *     where the new map will be placed.  If the map property is an
+     *     <OpenLayers.Map>, the layers from the context document will be added
+     *     to the map.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} A map based on the context.
+     */
+    read: function(data, options) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var version = this.version;
+        if(!version) {
+            version = root.getAttribute("version");
+        }
+        var parser = this.getParser(version);
+        var context = parser.read(data, options);
+        var map;
+        if(options && options.map) {
+            this.context = context;
+            if(options.map instanceof OpenLayers.Map) {
+                map = this.mergeContextToMap(context, options.map);
+            } else {
+                var mapOptions = options.map;
+                if(OpenLayers.Util.isElement(mapOptions) ||
+                   typeof mapOptions == "string") {
+                    // we assume mapOptions references a div
+                    // element
+                    mapOptions = {div: mapOptions};
+                }
+                map = this.contextToMap(context, mapOptions);
+            }
+        } else {
+            // not documented as part of the API, provided as a non-API option
+            map = context;
+        }
+        return map;
+    },
+
+    /**
+     * Method: getLayerFromContext
+     * Create a WMS layer from a layerContext object.
+     *
+     * Parameters:
+     * layerContext - {Object} An object representing a WMS layer.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMS>} A WMS layer.
+     */
+    getLayerFromContext: function(layerContext) {
+        var i, len;
+        // fill initial options object from layerContext
+        var options = {
+            queryable: layerContext.queryable, //keep queryable for api compatibility
+            visibility: layerContext.visibility,
+            maxExtent: layerContext.maxExtent,
+            metadata: OpenLayers.Util.applyDefaults(layerContext.metadata, 
+                {styles: layerContext.styles}),
+            numZoomLevels: layerContext.numZoomLevels,
+            units: layerContext.units,
+            isBaseLayer: layerContext.isBaseLayer,
+            opacity: layerContext.opacity,
+            displayInLayerSwitcher: layerContext.displayInLayerSwitcher,
+            singleTile: layerContext.singleTile,
+            tileSize: (layerContext.tileSize) ? 
+                new OpenLayers.Size(
+                    layerContext.tileSize.width, 
+                    layerContext.tileSize.height
+                ) : undefined,
+            minScale: layerContext.minScale || layerContext.maxScaleDenominator,
+            maxScale: layerContext.maxScale || layerContext.minScaleDenominator
+        };
+        if (this.layerOptions) {
+            OpenLayers.Util.applyDefaults(options, this.layerOptions);
+        }
+
+        var params = {
+            layers: layerContext.name,
+            transparent: layerContext.transparent,
+            version: layerContext.version
+        };
+        if (layerContext.formats && layerContext.formats.length>0) {
+            // set default value for params if current attribute is not positionned
+            params.format = layerContext.formats[0].value;
+            for (i=0, len=layerContext.formats.length; i<len; i++) {
+                var format = layerContext.formats[i];
+                if (format.current == true) {
+                    params.format = format.value;
+                    break;
+                }
+            }
+        }
+        if (layerContext.styles && layerContext.styles.length>0) {
+            for (i=0, len=layerContext.styles.length; i<len; i++) {
+                var style = layerContext.styles[i];
+                if (style.current == true) {
+                    // three style types to consider
+                    // 1) linked SLD
+                    // 2) inline SLD
+                    // 3) named style
+                    if(style.href) {
+                        params.sld = style.href;
+                    } else if(style.body) {
+                        params.sld_body = style.body;
+                    } else {
+                        params.styles = style.name;
+                    }
+                    break;
+                }
+            }
+        }
+        if (this.layerParams) {
+            OpenLayers.Util.applyDefaults(params, this.layerParams);
+        }
+
+        var layer = null;
+        var service = layerContext.service;
+        if (service == OpenLayers.Format.Context.serviceTypes.WFS) {
+            options.strategies = [new OpenLayers.Strategy.BBOX()];
+            options.protocol = new OpenLayers.Protocol.WFS({
+                url: layerContext.url,
+                // since we do not know featureNS, let the protocol
+                // determine it automagically using featurePrefix
+                featurePrefix: layerContext.name.split(":")[0],
+                featureType: layerContext.name.split(":").pop()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (service == OpenLayers.Format.Context.serviceTypes.KML) {
+            // use a vector layer with an HTTP Protcol and a Fixed strategy
+            options.strategies = [new OpenLayers.Strategy.Fixed()];
+            options.protocol = new OpenLayers.Protocol.HTTP({
+                url: layerContext.url, 
+                format: new OpenLayers.Format.KML()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (service == OpenLayers.Format.Context.serviceTypes.GML) {
+            // use a vector layer with a HTTP Protocol and a Fixed strategy
+            options.strategies = [new OpenLayers.Strategy.Fixed()];
+            options.protocol = new OpenLayers.Protocol.HTTP({
+                url: layerContext.url, 
+                format: new OpenLayers.Format.GML()
+            });
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+        } else if (layerContext.features) {
+            // inline GML or KML features
+            layer = new OpenLayers.Layer.Vector(
+                layerContext.title || layerContext.name,
+                options
+            );
+            layer.addFeatures(layerContext.features);
+        } else if (layerContext.categoryLayer !== true) {
+            layer = new OpenLayers.Layer.WMS(
+                layerContext.title || layerContext.name,
+                layerContext.url,
+                params,
+                options
+            );
+        }
+        return layer;
+    },
+
+    /**
+     * Method: getLayersFromContext
+     * Create an array of layers from an array of layerContext objects.
+     *
+     * Parameters:
+     * layersContext - {Array(Object)} An array of objects representing layers.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Layer>)} An array of layers.
+     */
+    getLayersFromContext: function(layersContext) {
+        var layers = [];
+        for (var i=0, len=layersContext.length; i<len; i++) {
+            var layer = this.getLayerFromContext(layersContext[i]);
+            if (layer !== null) {
+                layers.push(layer);
+            }
+        }
+        return layers;
+    },
+
+    /**
+     * Method: contextToMap
+     * Create a map given a context object.
+     *
+     * Parameters:
+     * context - {Object} The context object.
+     * options - {Object} Default map options.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} A map based on the context object.
+     */
+    contextToMap: function(context, options) {
+        options = OpenLayers.Util.applyDefaults({
+            maxExtent: context.maxExtent,
+            projection: context.projection
+        }, options);
+        var map = new OpenLayers.Map(options);
+        map.addLayers(this.getLayersFromContext(context.layersContext));
+        map.setCenter(
+            context.bounds.getCenterLonLat(),
+            map.getZoomForExtent(context.bounds, true)
+        );
+        return map;
+    },
+
+    /**
+     * Method: mergeContextToMap
+     * Add layers from a context object to a map.
+     *
+     * Parameters:
+     * context - {Object} The context object.
+     * map - {<OpenLayers.Map>} The map.
+     *
+     * Returns:
+     * {<OpenLayers.Map>} The same map with layers added.
+     */
+    mergeContextToMap: function(context, map) {
+        map.addLayers(this.getLayersFromContext(context.layersContext));
+        return map;
+    },
+
+    /**
+     * APIMethod: write
+     * Write a context document given a map.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Map> | Object} A map or context object.
+     * options - {Object} Optional configuration object.
+     *
+     * Returns:
+     * {String} A context document string.
+     */
+    write: function(obj, options) {
+        obj = this.toContext(obj);
+        var version = options && options.version;
+        var parser = this.getParser(version);
+        var context = parser.write(obj, options);
+        return context;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.Context"
+});
+
+/**
+ * Constant: OpenLayers.Format.Context.serviceTypes
+ * Enumeration for service types
+ */
+OpenLayers.Format.Context.serviceTypes = {
+    "WMS": "urn:ogc:serviceType:WMS",
+    "WFS": "urn:ogc:serviceType:WFS",
+    "WCS": "urn:ogc:serviceType:WCS",
+    "GML": "urn:ogc:serviceType:GML",
+    "SLD": "urn:ogc:serviceType:SLD",
+    "FES": "urn:ogc:serviceType:FES",
+    "KML": "urn:ogc:serviceType:KML"
+};


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter
___________________________________________________________________
Modified: svn:mergeinfo
   - 
   + /trunk/openlayers/lib/OpenLayers/Format/Filter:7565-7650,7733-10919

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,7 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Format/Filter.js
  * @requires OpenLayers/Format/XML.js
@@ -156,17 +156,6 @@
                 this.readChildNodes(node, filter);
                 obj.filters.push(filter);
             },
-            "PropertyIsLike": function(node, obj) {
-                var filter = new OpenLayers.Filter.Comparison({
-                    type: OpenLayers.Filter.Comparison.LIKE
-                });
-                this.readChildNodes(node, filter);
-                var wildCard = node.getAttribute("wildCard");
-                var singleChar = node.getAttribute("singleChar");
-                var esc = node.getAttribute("escape");
-                filter.value2regex(wildCard, singleChar, esc);
-                obj.filters.push(filter);
-            },
             "Literal": function(node, obj) {
                 obj.value = OpenLayers.String.numericIf(
                     this.getChildValue(node));
@@ -238,7 +227,7 @@
         var obj = {};
         this.readChildNodes(node, obj);
         var value = obj.value;
-        if(!value) {
+        if(value === undefined) {
             value = this.getChildValue(node);
         }
         return value;
@@ -348,18 +337,6 @@
                 this.writeNode("UpperBoundary", filter, node);
                 return node;
             },
-            "PropertyIsLike": function(filter) {
-                var node = this.createElementNSPlus("ogc:PropertyIsLike", {
-                    attributes: {
-                        wildCard: "*", singleChar: ".", escape: "!"
-                    }
-                });
-                // no ogc:expression handling for now
-                this.writeNode("PropertyName", filter, node);
-                // convert regex string to ogc string
-                this.writeNode("Literal", filter.regex2value(), node);
-                return node;
-            },
             "PropertyName": function(filter) {
                 // no ogc:expression handling for now
                 return this.createElementNSPlus("ogc:PropertyName", {

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -68,6 +69,17 @@
                 });
                 this.readChildNodes(node, filter);
                 obj.filters.push(filter);
+            },
+            "PropertyIsLike": function(node, obj) {
+                var filter = new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LIKE
+                });
+                this.readChildNodes(node, filter);
+                var wildCard = node.getAttribute("wildCard");
+                var singleChar = node.getAttribute("singleChar");
+                var esc = node.getAttribute("escape");
+                filter.value2regex(wildCard, singleChar, esc);
+                obj.filters.push(filter);
             }
         }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),
         "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"],
@@ -96,6 +108,18 @@
                 this.writeNode("Literal", filter.value, node);
                 return node;
             },
+            "PropertyIsLike": function(filter) {
+                var node = this.createElementNSPlus("ogc:PropertyIsLike", {
+                    attributes: {
+                        wildCard: "*", singleChar: ".", escape: "!"
+                    }
+                });
+                // no ogc:expression handling for now
+                this.writeNode("PropertyName", filter, node);
+                // convert regex string to ogc string
+                this.writeNode("Literal", filter.regex2value(), node);
+                return node;
+            },
             "BBOX": function(filter) {
                 var node = this.createElementNSPlus("ogc:BBOX");
                 this.writeNode("PropertyName", filter, node);

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Filter.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Format/XML.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/Base.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/Base.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/Base.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -331,12 +332,17 @@
                 // geometry or attributes.
                 var name;
                 var local = node.localName || node.nodeName.split(":").pop();
-                if (!this.singleFeatureType && 
-                    (OpenLayers.Util.indexOf(this.featureType, local) != -1)) {
+                // Since an attribute can have the same name as the feature type
+                // we only want to read the node as a feature if the parent
+                // node can have feature nodes as children.  In this case, the
+                // obj.features property is set.
+                if (obj.features) {
+                    if (!this.singleFeatureType &&
+                        (OpenLayers.Util.indexOf(this.featureType, local) !== -1)) {
                         name = "_typeName";
-                }
-                else if(local == this.featureType) {
-                    name = "_typeName";
+                    } else if(local === this.featureType) {
+                        name = "_typeName";
+                    }
                 } else {
                     // Assume attribute elements have one child node and that the child
                     // is a text node.  Otherwise assume it is a geometry node.
@@ -379,7 +385,7 @@
                     );
                 }
                 if(container.bounds) {
-                    feature.geometry.bounds = container.bounds;
+                    feature.bounds = container.bounds;
                 }
                 obj.features.push(feature);
             },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v2.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v2.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v3.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v3.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GML/v3.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -140,14 +141,16 @@
         // only accept one geometry per feature - look for highest "order"
         var order = ["MultiPolygon", "Polygon",
                      "MultiLineString", "LineString",
-                     "MultiPoint", "Point", "Envelope", "Box"];
+                     "MultiPoint", "Point", "Envelope"];
+        // FIXME: In case we parse a feature with no geometry, but boundedBy an Envelope,
+        // this code creates a geometry derived from the Envelope. This is not correct.
         var type, nodeList, geometry, parser;
         for(var i=0; i<order.length; ++i) {
             type = order[i];
             nodeList = this.getElementsByTagNameNS(node, this.gmlns, type);
             if(nodeList.length > 0) {
                 // only deal with first geometry of this type
-                var parser = this.parseGeometry[type.toLowerCase()];
+                parser = this.parseGeometry[type.toLowerCase()];
                 if(parser) {
                     geometry = parser.apply(this, [nodeList[0]]);
                     if (this.internalProjection && this.externalProjection) {
@@ -162,6 +165,21 @@
                 break;
             }
         }
+
+        var bounds;
+        var boxNodes = this.getElementsByTagNameNS(node, this.gmlns, "Box");
+        for(i=0; i<boxNodes.length; ++i) {
+            var boxNode = boxNodes[i];
+            var box = this.parseGeometry["box"].apply(this, [boxNode]);
+            var parentNode = boxNode.parentNode;
+            var parentName = parentNode.localName ||
+                             parentNode.nodeName.split(":").pop();
+            if(parentName === "boundedBy") {
+                bounds = box;
+            } else {
+                geometry = box.toGeometry();
+            }
+        }
         
         // construct feature (optionally with attributes)
         var attributes;
@@ -169,6 +187,7 @@
             attributes = this.parseAttributes(node);
         }
         var feature = new OpenLayers.Feature.Vector(geometry, attributes);
+        feature.bounds = bounds;
         
         feature.gml = {
             featureType: node.firstChild.nodeName.split(":")[1],
@@ -522,7 +541,40 @@
                 envelope = new OpenLayers.Geometry.Polygon([ring]);
             }
             return envelope; 
+        },
+
+        /**
+         * Method: parseGeometry.box
+         * Given a GML node representing a box geometry, create an
+         *     OpenLayers.Bounds.
+         *
+         * Parameters:
+         * node - {DOMElement} A GML node.
+         *
+         * Returns:
+         * {<OpenLayers.Bounds>} A bounds representing the box.
+         */
+        box: function(node) {
+            var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+                                                   "coordinates");
+            var coordString;
+            var coords, beginPoint = null, endPoint = null;
+            if (nodeList.length > 0) {
+                coordString = nodeList[0].firstChild.nodeValue;
+                coords = coordString.split(" ");
+                if (coords.length == 2) {
+                    beginPoint = coords[0].split(",");
+                    endPoint = coords[1].split(",");
+                }
+            }
+            if (beginPoint !== null && endPoint !== null) {
+                return new OpenLayers.Bounds(parseFloat(beginPoint[0]),
+                    parseFloat(beginPoint[1]),
+                    parseFloat(endPoint[0]),
+                    parseFloat(endPoint[1]) );
+            }
         }
+        
     },
     
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GPX.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GPX.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GPX.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,12 +1,14 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Format/XML.js
  * @requires OpenLayers/Feature/Vector.js
  * @requires OpenLayers/Geometry/Point.js
  * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Projection.js
  */
 
 /**
@@ -53,6 +55,9 @@
      *     this instance.
      */
     initialize: function(options) {
+        // GPX coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
         OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
     },
     

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoJSON.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoJSON.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoJSON.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -25,6 +26,13 @@
 OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {
 
     /**
+     * APIProperty: ignoreExtraDims
+     * {Boolean} Ignore dimensions higher than 2 when reading geometry
+     * coordinates.
+     */ 
+    ignoreExtraDims: false,
+    
+    /**
      * Constructor: OpenLayers.Format.GeoJSON
      * Create a new parser for GeoJSON.
      *
@@ -269,8 +277,9 @@
          * {<OpenLayers.Geometry>} A geometry.
          */
         "point": function(array) {
-            if(array.length != 2) {
-                throw "Only 2D points are supported: " + array;
+            if (this.ignoreExtraDims == false && 
+                  array.length != 2) {
+                    throw "Only 2D points are supported: " + array;
             }
             return new OpenLayers.Geometry.Point(array[0], array[1]);
         },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoRSS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoRSS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/GeoRSS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/JSON.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/JSON.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/JSON.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/KML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/KML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/KML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -11,11 +12,12 @@
  * @requires OpenLayers/Geometry/Collection.js
  * @requires OpenLayers/Request/XMLHttpRequest.js
  * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Projection.js
  */
 
 /**
  * Class: OpenLayers.Format.KML
- * Read/Wite KML. Create a new instance with the <OpenLayers.Format.KML>
+ * Read/Write KML. Create a new instance with the <OpenLayers.Format.KML>
  *     constructor. 
  * 
  * Inherits from:
@@ -24,6 +26,15 @@
 OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
     
     /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        kml: "http://www.opengis.net/kml/2.2",
+        gx: "http://www.google.com/kml/ext/2.2"
+    },
+
+    /**
      * APIProperty: kmlns
      * {String} KML Namespace to use. Defaults to 2.0 namespace.
      */
@@ -31,19 +42,21 @@
     
     /** 
      * APIProperty: placemarksDesc
-     * {String} Name of the placemarks.  Default is "No description available."
+     * {String} Name of the placemarks.  Default is "No description available".
      */
     placemarksDesc: "No description available",
     
     /** 
      * APIProperty: foldersName
-     * {String} Name of the folders.  Default is "OpenLayers export."
+     * {String} Name of the folders.  Default is "OpenLayers export".
+     *          If set to null, no name element will be created.
      */
     foldersName: "OpenLayers export",
     
     /** 
      * APIProperty: foldersDesc
      * {String} Description of the folders. Default is "Exported on [date]."
+     *          If set to null, no description element will be created.
      */
     foldersDesc: "Exported on " + new Date(),
     
@@ -63,6 +76,26 @@
     extractStyles: false,
     
     /**
+     * APIProperty: extractTracks
+     * {Boolean} Extract gx:Track elements from Placemark elements.  Default
+     *     is false.  If true, features will be generated for all points in
+     *     all gx:Track elements.  Features will have a when (Date) attribute
+     *     based on when elements in the track.  If tracks include angle
+     *     elements, features will have heading, tilt, and roll attributes.
+     *     If track point coordinates have three values, features will have
+     *     an altitude attribute with the third coordinate value.
+     */
+    extractTracks: false,
+    
+    /**
+     * APIProperty: trackAttributes
+     * {Array} If <extractTracks> is true, points within gx:Track elements will 
+     *     be parsed as features with when, heading, tilt, and roll attributes.
+     *     Any additional attribute names can be provided in <trackAttributes>.
+     */
+    trackAttributes: null,
+    
+    /**
      * Property: internalns
      * {String} KML Namespace to use -- defaults to the namespace of the
      *     Placemark node being parsed, but falls back to kmlns. 
@@ -122,6 +155,9 @@
             kmlIconPalette: (/root:\/\/icons\/palette-(\d+)(\.\w+)/),
             straightBracket: (/\$\[(.*?)\]/g)
         };
+        // KML coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
         OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
     },
 
@@ -271,7 +307,7 @@
         for(var i=0, len=nodes.length; i<len; i++) {
             var style = this.parseStyle(nodes[i]);
             if(style) {
-                styleName = (options.styleBaseUrl || "") + "#" + style.id;
+                var styleName = (options.styleBaseUrl || "") + "#" + style.id;
                 
                 this.styles[styleName] = style;
             }
@@ -279,6 +315,31 @@
     },
 
     /**
+     * Method: parseKmlColor
+     * Parses a kml color (in 'aabbggrr' format) and returns the corresponding 
+     * color and opacity or null if the color is invalid.
+     *
+     * Parameters: 
+     * kmlColor - {String} a kml formated color
+     *
+     * Returns:
+     * {Object}
+     */
+    parseKmlColor: function(kmlColor) {
+        var color = null;
+        if (kmlColor) {
+            var matches = kmlColor.match(this.regExes.kmlColor);
+            if (matches) {
+                color = {
+                    color: '#' + matches[4] + matches[3] + matches[2],
+                    opacity: parseInt(matches[1], 16) / 255
+                };
+            }
+        }
+        return color;
+    },
+
+    /**
      * Method: parseStyle
      * Parses the children of a <Style> node and builds the style hash
      * accordingly
@@ -290,7 +351,8 @@
     parseStyle: function(node) {
         var style = {};
         
-        var types = ["LineStyle", "PolyStyle", "IconStyle", "BalloonStyle"];
+        var types = ["LineStyle", "PolyStyle", "IconStyle", "BalloonStyle", 
+                     "LabelStyle"];
         var type, nodeList, geometry, parser;
         for(var i=0, len=types.length; i<len; ++i) {
             type = types[i];
@@ -303,50 +365,39 @@
             // only deal with first geometry of this type
             switch (type.toLowerCase()) {
                 case "linestyle":
-                    var color = this.parseProperty(styleTypeNode, "*", "color");
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
                     if (color) {
-                        var matches = (color.toString()).match(
-                                                         this.regExes.kmlColor);
-
-                        // transparency
-                        var alpha = matches[1];
-                        style["strokeOpacity"] = parseInt(alpha, 16) / 255;
-
-                        // rgb colors (google uses bgr)
-                        var b = matches[2]; 
-                        var g = matches[3]; 
-                        var r = matches[4]; 
-                        style["strokeColor"] = "#" + r + g + b;
+                        style["strokeColor"] = color.color;
+                        style["strokeOpacity"] = color.opacity;
                     }
                     
                     var width = this.parseProperty(styleTypeNode, "*", "width");
                     if (width) {
                         style["strokeWidth"] = width;
                     }
+                    break;
 
                 case "polystyle":
-                    var color = this.parseProperty(styleTypeNode, "*", "color");
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
                     if (color) {
-                        var matches = (color.toString()).match(
-                                                         this.regExes.kmlColor);
-
-                        // transparency
-                        var alpha = matches[1];
-                        style["fillOpacity"] = parseInt(alpha, 16) / 255;
-
-                        // rgb colors (google uses bgr)
-                        var b = matches[2]; 
-                        var g = matches[3]; 
-                        var r = matches[4]; 
-                        style["fillColor"] = "#" + r + g + b;
+                        style["fillOpacity"] = color.opacity;
+                        style["fillColor"] = color.color;
                     }
-                     // Check is fill is disabled
+                    // Check if fill is disabled
                     var fill = this.parseProperty(styleTypeNode, "*", "fill");
                     if (fill == "0") {
                         style["fillColor"] = "none";
                     }
+                    // Check if outline is disabled
+                    var outline = this.parseProperty(styleTypeNode, "*", "outline");
+                    if (outline == "0") {
+                        style["strokeWidth"] = "0";
+                    }
                    
                     break;
+
                 case "iconstyle":
                     // set scale
                     var scale = parseFloat(this.parseProperty(styleTypeNode, 
@@ -464,6 +515,15 @@
                                        this.regExes.straightBracket, "${$1}");
                     }
                     break;
+                case "labelstyle":
+                    var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+                    var color = this.parseKmlColor(kmlColor);
+                    if (color) {
+                        style["fontColor"] = color.color;
+                        style["fontOpacity"] = color.opacity;
+                    }
+                    break;
+
                 default:
             }
         }
@@ -535,7 +595,7 @@
      * 
      */
     parseFeatures: function(nodes, options) {
-        var features = new Array(nodes.length);
+        var features = [];
         for(var i=0, len=nodes.length; i<len; i++) {
             var featureNode = nodes[i];
             var feature = this.parseFeature.apply(this,[featureNode]) ;
@@ -563,8 +623,26 @@
                     }
                 }
 
-                // add feature to list of features
-                features[i] = feature;
+                // check if gx:Track elements should be parsed
+                if (this.extractTracks) {
+                    var tracks = this.getElementsByTagNameNS(
+                        featureNode, this.namespaces.gx, "Track"
+                    );
+                    if (tracks && tracks.length > 0) {
+                        var track = tracks[0];
+                        var container = {
+                            features: [],
+                            feature: feature
+                        };
+                        this.readNode(track, container);
+                        if (container.features.length > 0) {
+                            features.push.apply(features, container.features);
+                        }
+                    }
+                } else {
+                    // add feature to list of features
+                    features.push(feature);                    
+                }
             } else {
                 throw "Bad Placemark: " + i;
             }
@@ -573,8 +651,101 @@
         // add new features to existing feature list
         this.features = this.features.concat(features);
     },
-
+    
     /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "kml": {
+            "when": function(node, container) {
+                container.whens.push(OpenLayers.Date.parse(
+                    this.getChildValue(node)
+                ));
+            },
+            "_trackPointAttribute": function(node, container) {
+                var name = node.nodeName.split(":").pop();
+                container.attributes[name].push(this.getChildValue(node));
+            }
+        },
+        "gx": {
+            "Track": function(node, container) {
+                var obj = {
+                    whens: [],
+                    points: [],
+                    angles: []
+                };
+                if (this.trackAttributes) {
+                    var name;
+                    obj.attributes = {};
+                    for (var i=0, ii=this.trackAttributes.length; i<ii; ++i) {
+                        name = this.trackAttributes[i];
+                        obj.attributes[name] = [];
+                        if (!(name in this.readers.kml)) {
+                            this.readers.kml[name] = this.readers.kml._trackPointAttribute;
+                        }
+                    }
+                }
+                this.readChildNodes(node, obj);
+                if (obj.whens.length !== obj.points.length) {
+                    throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:coord (" + obj.points.length + ") elements.");
+                }
+                var hasAngles = obj.angles.length > 0;
+                if (hasAngles && obj.whens.length !== obj.angles.length) {
+                    throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:angles (" + obj.angles.length + ") elements.");
+                }
+                var feature, point, angles;
+                for (var i=0, ii=obj.whens.length; i<ii; ++i) {
+                    feature = container.feature.clone();
+                    feature.fid = container.feature.fid || container.feature.id;
+                    point = obj.points[i];
+                    feature.geometry = point;
+                    if ("z" in point) {
+                        feature.attributes.altitude = point.z;
+                    }
+                    if (this.internalProjection && this.externalProjection) {
+                        feature.geometry.transform(
+                            this.externalProjection, this.internalProjection
+                        ); 
+                    }
+                    if (this.trackAttributes) {
+                        for (var j=0, jj=this.trackAttributes.length; j<jj; ++j) {
+                            feature.attributes[name] = obj.attributes[this.trackAttributes[j]][i];
+                        }
+                    }
+                    feature.attributes.when = obj.whens[i];
+                    feature.attributes.trackId = container.feature.id;
+                    if (hasAngles) {
+                        angles = obj.angles[i];
+                        feature.attributes.heading = parseFloat(angles[0]);
+                        feature.attributes.tilt = parseFloat(angles[1]);
+                        feature.attributes.roll = parseFloat(angles[2]);
+                    }
+                    container.features.push(feature);
+                }
+            },
+            "coord": function(node, container) {
+                var str = this.getChildValue(node);
+                var coords = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+                var point = new OpenLayers.Geometry.Point(coords[0], coords[1]);
+                if (coords.length > 2) {
+                    point.z = parseFloat(coords[2]);
+                }
+                container.points.push(point);
+            },
+            "angles": function(node, container) {
+                var str = this.getChildValue(node);
+                var parts = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+                container.angles.push(parts);
+            }
+        }
+    },
+    
+    /**
      * Method: parseFeature
      * This function is the core of the KML parsing code in OpenLayers.
      *     It creates the geometries that are then attached to the returned
@@ -855,12 +1026,18 @@
             child = children[i];
             if(child.nodeType == 1) {
                 grandchildren = child.childNodes;
-                if(grandchildren.length == 1 || grandchildren.length == 3) {
+                if(grandchildren.length >= 1 && grandchildren.length <= 3) {
                     var grandchild;
                     switch (grandchildren.length) {
                         case 1:
                             grandchild = grandchildren[0];
                             break;
+                        case 2:
+                            var c1 = grandchildren[0];
+                            var c2 = grandchildren[1];
+                            grandchild = (c1.nodeType == 3 || c1.nodeType == 4) ?
+                                c1 : c2;
+                            break;
                         case 3:
                         default:
                             grandchild = grandchildren[1];
@@ -884,16 +1061,17 @@
 
     /**
      * Method: parseExtendedData
-     * Parse ExtendedData from KML. No support for schemas/datatypes.
+     * Parse ExtendedData from KML. Limited support for schemas/datatypes.
      *     See http://code.google.com/apis/kml/documentation/kmlreference.html#extendeddata
      *     for more information on extendeddata.
      */
     parseExtendedData: function(node) {
         var attributes = {};
+        var i, len, data, key;
         var dataNodes = node.getElementsByTagName("Data");
-        for (var i = 0, len = dataNodes.length; i < len; i++) {
-            var data = dataNodes[i];
-            var key = data.getAttribute("name");
+        for (i = 0, len = dataNodes.length; i < len; i++) {
+            data = dataNodes[i];
+            key = data.getAttribute("name");
             var ed = {};
             var valueNode = data.getElementsByTagName("value");
             if (valueNode.length) {
@@ -905,6 +1083,16 @@
             }
             attributes[key] = ed;
         }
+        var simpleDataNodes = node.getElementsByTagName("SimpleData");
+        for (i = 0, len = simpleDataNodes.length; i < len; i++) {
+            var ed = {};
+            data = simpleDataNodes[i];
+            key = data.getAttribute("name");
+            ed['value'] = this.getChildValue(data);
+            ed['displayName'] = key;
+            attributes[key] = ed;
+        }
+        
         return attributes;    
     },
     
@@ -963,21 +1151,25 @@
      * {DOMElement}
      */
     createFolderXML: function() {
+        // Folder
+        var folder = this.createElementNS(this.kmlns, "Folder");
+
         // Folder name
-        var folderName = this.createElementNS(this.kmlns, "name");
-        var folderNameText = this.createTextNode(this.foldersName); 
-        folderName.appendChild(folderNameText);
+        if (this.foldersName) {
+            var folderName = this.createElementNS(this.kmlns, "name");
+            var folderNameText = this.createTextNode(this.foldersName); 
+            folderName.appendChild(folderNameText);
+            folder.appendChild(folderName);
+        }
 
         // Folder description
-        var folderDesc = this.createElementNS(this.kmlns, "description");        
-        var folderDescText = this.createTextNode(this.foldersDesc); 
-        folderDesc.appendChild(folderDescText);
+        if (this.foldersDesc) {
+            var folderDesc = this.createElementNS(this.kmlns, "description");        
+            var folderDescText = this.createTextNode(this.foldersDesc); 
+            folderDesc.appendChild(folderDescText);
+            folder.appendChild(folderDesc);
+        }
 
-        // Folder
-        var folder = this.createElementNS(this.kmlns, "Folder");
-        folder.appendChild(folderName);
-        folder.appendChild(folderDesc);
-        
         return folder;
     },
 
@@ -994,14 +1186,13 @@
     createPlacemarkXML: function(feature) {        
         // Placemark name
         var placemarkName = this.createElementNS(this.kmlns, "name");
-        var name = (feature.attributes.name) ?
-                    feature.attributes.name : feature.id;
+        var name = feature.style && feature.style.label ? feature.style.label :
+                   feature.attributes.name || feature.id;
         placemarkName.appendChild(this.createTextNode(name));
 
         // Placemark description
         var placemarkDesc = this.createElementNS(this.kmlns, "description");
-        var desc = (feature.attributes.description) ?
-                    feature.attributes.description : this.placemarksDesc;
+        var desc = feature.attributes.description || this.placemarksDesc;
         placemarkDesc.appendChild(this.createTextNode(desc));
         
         // Placemark

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/OSM.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OSM.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OSM.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Format/XML.js
@@ -8,6 +9,7 @@
  * @requires OpenLayers/Geometry/Point.js
  * @requires OpenLayers/Geometry/LineString.js
  * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Projection.js
  */
 
 /**  
@@ -73,6 +75,9 @@
             area[layer_defaults.areaTags[i]] = true;
         }
         layer_defaults.areaTags = area;
+
+        // OSM coordinates are always in longlat WGS84
+        this.externalProjection = new OpenLayers.Projection("EPSG:4326");
         
         OpenLayers.Format.XML.prototype.initialize.apply(this, [layer_defaults]);
     },

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,256 +0,0 @@
-/* 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/Format/XML.js
- */
-
-if (!OpenLayers.Format.OWSCommon) {
-    OpenLayers.Format.OWSCommon = {};
-}
-
-/**
- * Class: OpenLayers.Format.OWSCommon.v1
- * Common readers and writers for OWSCommon v1.X formats
- */
-OpenLayers.Format.OWSCommon.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
-   
-    /**
-     * Property: regExes
-     * Compiled regular expressions for manipulating strings.
-     */
-    regExes: {
-        trimSpace: (/^\s*|\s*$/g),
-        removeSpace: (/\s*/g),
-        splitSpace: (/\s+/),
-        trimComma: (/\s*,\s*/g)
-    },
-
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "ows": {
-            "ServiceIdentification": function(node, obj) {
-                obj.serviceIdentification = {};
-                this.readChildNodes(node, obj.serviceIdentification);
-            },
-            "Title": function(node, obj) {
-                obj.title = this.getChildValue(node);
-            },
-            "Abstract": function(node, serviceIdentification) {
-                serviceIdentification["abstract"] = this.getChildValue(node);
-            },
-            "Keywords": function(node, serviceIdentification) {
-                serviceIdentification.keywords = {};
-                this.readChildNodes(node, serviceIdentification.keywords);
-            },
-            "Keyword": function(node, keywords) {
-                keywords[this.getChildValue(node)] = true;
-            },
-            "ServiceType": function(node, serviceIdentification) {
-                serviceIdentification.serviceType = {
-                    codeSpace: node.getAttribute('codeSpace'), 
-                    value: this.getChildValue(node)};
-            },
-            "ServiceTypeVersion": function(node, serviceIdentification) {
-                serviceIdentification.serviceTypeVersion = this.getChildValue(node);
-            },
-            "Fees": function(node, serviceIdentification) {
-                serviceIdentification.fees = this.getChildValue(node);
-            },
-            "AccessConstraints": function(node, serviceIdentification) {
-                serviceIdentification.accessConstraints = 
-                    this.getChildValue(node);
-            },
-            "ServiceProvider": function(node, obj) {
-                obj.serviceProvider = {};
-                this.readChildNodes(node, obj.serviceProvider);
-            },
-            "ProviderName": function(node, serviceProvider) {
-                serviceProvider.providerName = this.getChildValue(node);
-            },
-            "ProviderSite": function(node, serviceProvider) {
-                serviceProvider.providerSite = this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href");
-            },
-            "ServiceContact": function(node, serviceProvider) {
-                serviceProvider.serviceContact = {};
-                this.readChildNodes(node, serviceProvider.serviceContact);
-            },
-            "IndividualName": function(node, serviceContact) {
-                serviceContact.individualName = this.getChildValue(node);
-            },
-            "PositionName": function(node, serviceContact) {
-                serviceContact.positionName = this.getChildValue(node);
-            },
-            "ContactInfo": function(node, serviceContact) {
-                serviceContact.contactInfo = {};
-                this.readChildNodes(node, serviceContact.contactInfo);
-            },
-            "Phone": function(node, contactInfo) {
-                contactInfo.phone = {};
-                this.readChildNodes(node, contactInfo.phone);
-            },
-            "Voice": function(node, phone) {
-                phone.voice = this.getChildValue(node);
-            },
-            "Address": function(node, contactInfo) {
-                contactInfo.address = {};
-                this.readChildNodes(node, contactInfo.address);
-            },
-            "DeliveryPoint": function(node, address) {
-                address.deliveryPoint = this.getChildValue(node);
-            },
-            "City": function(node, address) {
-                address.city = this.getChildValue(node);
-            },
-            "AdministrativeArea": function(node, address) {
-                address.administrativeArea = this.getChildValue(node);
-            },
-            "PostalCode": function(node, address) {
-                address.postalCode = this.getChildValue(node);
-            },
-            "Country": function(node, address) {
-                address.country = this.getChildValue(node);
-            },
-            "ElectronicMailAddress": function(node, address) {
-                address.electronicMailAddress = this.getChildValue(node);
-            },
-            "Role": function(node, serviceContact) {
-                serviceContact.role = this.getChildValue(node);
-            },
-            "OperationsMetadata": function(node, obj) {
-                obj.operationsMetadata = {};
-                this.readChildNodes(node, obj.operationsMetadata);
-            },
-            "Operation": function(node, operationsMetadata) {
-                var name = node.getAttribute("name");
-                operationsMetadata[name] = {};
-                this.readChildNodes(node, operationsMetadata[name]);
-            },
-            "DCP": function(node, operation) {
-                operation.dcp = {};
-                this.readChildNodes(node, operation.dcp);
-            },
-            "HTTP": function(node, dcp) {
-                dcp.http = {};
-                this.readChildNodes(node, dcp.http);
-            },
-            "Get": function(node, http) {
-                http.get = this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href");
-            },
-            "Post": function(node, http) {
-                http.post = this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href");
-            },
-            "Parameter": function(node, operation) {
-                if (!operation.parameters) {
-                    operation.parameters = {};
-                }
-                var name = node.getAttribute("name");
-                operation.parameters[name] = {};
-                this.readChildNodes(node, operation.parameters[name]);
-            },
-            "Value": function(node, allowedValues) {
-                allowedValues[this.getChildValue(node)] = true;
-            },
-            "OutputFormat": function(node, obj) {
-                obj.formats.push({value: this.getChildValue(node)});
-                this.readChildNodes(node, obj);
-            },
-            "WGS84BoundingBox": function(node, obj) {
-                var boundingBox = {};
-                boundingBox.crs = node.getAttribute("crs");
-                if (obj.BoundingBox) {
-                    obj.BoundingBox.push(boundingBox);
-                } else {
-                    obj.projection = boundingBox.crs;
-                    boundingBox = obj;
-               }
-               this.readChildNodes(node, boundingBox);
-            },
-            "BoundingBox": function(node, obj) {
-                // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox
-                // LowerCorner = "min_x min_y"
-                // UpperCorner = "max_x max_y"
-                // It should normally depend on the projection
-                this.readers['ows']['WGS84BoundingBox'].apply(this, [node, obj]);
-            },
-            "LowerCorner": function(node, obj) {
-                var str = this.getChildValue(node).replace(
-                    this.regExes.trimSpace, "");
-                str = str.replace(this.regExes.trimComma, ",");
-                var pointList = str.split(this.regExes.splitSpace);
-                obj.left = pointList[0];
-                obj.bottom = pointList[1];
-            },
-            "UpperCorner": function(node, obj) {
-                var str = this.getChildValue(node).replace(
-                    this.regExes.trimSpace, "");
-                str = str.replace(this.regExes.trimComma, ",");
-                var pointList = str.split(this.regExes.splitSpace);
-                obj.right = pointList[0];
-                obj.top = pointList[1];
-                obj.bounds = new OpenLayers.Bounds(obj.left, obj.bottom,
-                    obj.right, obj.top);
-                delete obj.left;
-                delete obj.bottom;
-                delete obj.right;
-                delete obj.top;
-            }
-        }
-    },
-
-    /**
-     * Property: writers
-     * As a compliment to the readers property, this structure contains public
-     *     writing functions grouped by namespace alias and named like the
-     *     node names they produce.
-     */
-    writers: {
-        "ows": {
-            "BoundingBox": function(options) {
-                var node = this.createElementNSPlus("ows:BoundingBox", {
-                    attributes: {
-                        crs: options.projection
-                    }
-                });
-                this.writeNode("ows:LowerCorner", options, node);
-                this.writeNode("ows:UpperCorner", options, node);
-                return node;
-            },
-            "LowerCorner": function(options) {
-                var node = this.createElementNSPlus("ows:LowerCorner", {
-                    value: options.bounds.left + " " + options.bounds.bottom });
-                return node;
-            },
-            "UpperCorner": function(options) {
-                var node = this.createElementNSPlus("ows:UpperCorner", {
-                    value: options.bounds.right + " " + options.bounds.top });
-                return node;
-            },
-            "Title": function(title) {
-                var node = this.createElementNSPlus("ows:Title", {
-                    value: title });
-                return node;
-            },
-            "OutputFormat": function(format) {
-                var node = this.createElementNSPlus("ows:OutputFormat", {
-                    value: format });
-                return node;
-            }
-        }
-    },
-
-    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1"
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,256 @@
+/* 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/Format/XML.js
+ */
+
+if (!OpenLayers.Format.OWSCommon) {
+    OpenLayers.Format.OWSCommon = {};
+}
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1
+ * Common readers and writers for OWSCommon v1.X formats
+ */
+OpenLayers.Format.OWSCommon.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+   
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": {
+            "ServiceIdentification": function(node, obj) {
+                obj.serviceIdentification = {};
+                this.readChildNodes(node, obj.serviceIdentification);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+            },
+            "Abstract": function(node, serviceIdentification) {
+                serviceIdentification["abstract"] = this.getChildValue(node);
+            },
+            "Keywords": function(node, serviceIdentification) {
+                serviceIdentification.keywords = {};
+                this.readChildNodes(node, serviceIdentification.keywords);
+            },
+            "Keyword": function(node, keywords) {
+                keywords[this.getChildValue(node)] = true;
+            },
+            "ServiceType": function(node, serviceIdentification) {
+                serviceIdentification.serviceType = {
+                    codeSpace: node.getAttribute('codeSpace'), 
+                    value: this.getChildValue(node)};
+            },
+            "ServiceTypeVersion": function(node, serviceIdentification) {
+                serviceIdentification.serviceTypeVersion = this.getChildValue(node);
+            },
+            "Fees": function(node, serviceIdentification) {
+                serviceIdentification.fees = this.getChildValue(node);
+            },
+            "AccessConstraints": function(node, serviceIdentification) {
+                serviceIdentification.accessConstraints = 
+                    this.getChildValue(node);
+            },
+            "ServiceProvider": function(node, obj) {
+                obj.serviceProvider = {};
+                this.readChildNodes(node, obj.serviceProvider);
+            },
+            "ProviderName": function(node, serviceProvider) {
+                serviceProvider.providerName = this.getChildValue(node);
+            },
+            "ProviderSite": function(node, serviceProvider) {
+                serviceProvider.providerSite = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "ServiceContact": function(node, serviceProvider) {
+                serviceProvider.serviceContact = {};
+                this.readChildNodes(node, serviceProvider.serviceContact);
+            },
+            "IndividualName": function(node, serviceContact) {
+                serviceContact.individualName = this.getChildValue(node);
+            },
+            "PositionName": function(node, serviceContact) {
+                serviceContact.positionName = this.getChildValue(node);
+            },
+            "ContactInfo": function(node, serviceContact) {
+                serviceContact.contactInfo = {};
+                this.readChildNodes(node, serviceContact.contactInfo);
+            },
+            "Phone": function(node, contactInfo) {
+                contactInfo.phone = {};
+                this.readChildNodes(node, contactInfo.phone);
+            },
+            "Voice": function(node, phone) {
+                phone.voice = this.getChildValue(node);
+            },
+            "Address": function(node, contactInfo) {
+                contactInfo.address = {};
+                this.readChildNodes(node, contactInfo.address);
+            },
+            "DeliveryPoint": function(node, address) {
+                address.deliveryPoint = this.getChildValue(node);
+            },
+            "City": function(node, address) {
+                address.city = this.getChildValue(node);
+            },
+            "AdministrativeArea": function(node, address) {
+                address.administrativeArea = this.getChildValue(node);
+            },
+            "PostalCode": function(node, address) {
+                address.postalCode = this.getChildValue(node);
+            },
+            "Country": function(node, address) {
+                address.country = this.getChildValue(node);
+            },
+            "ElectronicMailAddress": function(node, address) {
+                address.electronicMailAddress = this.getChildValue(node);
+            },
+            "Role": function(node, serviceContact) {
+                serviceContact.role = this.getChildValue(node);
+            },
+            "OperationsMetadata": function(node, obj) {
+                obj.operationsMetadata = {};
+                this.readChildNodes(node, obj.operationsMetadata);
+            },
+            "Operation": function(node, operationsMetadata) {
+                var name = node.getAttribute("name");
+                operationsMetadata[name] = {};
+                this.readChildNodes(node, operationsMetadata[name]);
+            },
+            "DCP": function(node, operation) {
+                operation.dcp = {};
+                this.readChildNodes(node, operation.dcp);
+            },
+            "HTTP": function(node, dcp) {
+                dcp.http = {};
+                this.readChildNodes(node, dcp.http);
+            },
+            "Get": function(node, http) {
+                http.get = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "Post": function(node, http) {
+                http.post = this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href");
+            },
+            "Parameter": function(node, operation) {
+                if (!operation.parameters) {
+                    operation.parameters = {};
+                }
+                var name = node.getAttribute("name");
+                operation.parameters[name] = {};
+                this.readChildNodes(node, operation.parameters[name]);
+            },
+            "Value": function(node, allowedValues) {
+                allowedValues[this.getChildValue(node)] = true;
+            },
+            "OutputFormat": function(node, obj) {
+                obj.formats.push({value: this.getChildValue(node)});
+                this.readChildNodes(node, obj);
+            },
+            "WGS84BoundingBox": function(node, obj) {
+                var boundingBox = {};
+                boundingBox.crs = node.getAttribute("crs");
+                if (obj.BoundingBox) {
+                    obj.BoundingBox.push(boundingBox);
+                } else {
+                    obj.projection = boundingBox.crs;
+                    boundingBox = obj;
+               }
+               this.readChildNodes(node, boundingBox);
+            },
+            "BoundingBox": function(node, obj) {
+                // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox
+                // LowerCorner = "min_x min_y"
+                // UpperCorner = "max_x max_y"
+                // It should normally depend on the projection
+                this.readers['ows']['WGS84BoundingBox'].apply(this, [node, obj]);
+            },
+            "LowerCorner": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, "");
+                str = str.replace(this.regExes.trimComma, ",");
+                var pointList = str.split(this.regExes.splitSpace);
+                obj.left = pointList[0];
+                obj.bottom = pointList[1];
+            },
+            "UpperCorner": function(node, obj) {
+                var str = this.getChildValue(node).replace(
+                    this.regExes.trimSpace, "");
+                str = str.replace(this.regExes.trimComma, ",");
+                var pointList = str.split(this.regExes.splitSpace);
+                obj.right = pointList[0];
+                obj.top = pointList[1];
+                obj.bounds = new OpenLayers.Bounds(obj.left, obj.bottom,
+                    obj.right, obj.top);
+                delete obj.left;
+                delete obj.bottom;
+                delete obj.right;
+                delete obj.top;
+            }
+        }
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ows": {
+            "BoundingBox": function(options) {
+                var node = this.createElementNSPlus("ows:BoundingBox", {
+                    attributes: {
+                        crs: options.projection
+                    }
+                });
+                this.writeNode("ows:LowerCorner", options, node);
+                this.writeNode("ows:UpperCorner", options, node);
+                return node;
+            },
+            "LowerCorner": function(options) {
+                var node = this.createElementNSPlus("ows:LowerCorner", {
+                    value: options.bounds.left + " " + options.bounds.bottom });
+                return node;
+            },
+            "UpperCorner": function(options) {
+                var node = this.createElementNSPlus("ows:UpperCorner", {
+                    value: options.bounds.right + " " + options.bounds.top });
+                return node;
+            },
+            "Title": function(title) {
+                var node = this.createElementNSPlus("ows:Title", {
+                    value: title });
+                return node;
+            },
+            "OutputFormat": function(format) {
+                var node = this.createElementNSPlus("ows:OutputFormat", {
+                    value: format });
+                return node;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1"
+
+});

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,50 +0,0 @@
-/* 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/Format/OWSCommon/v1.js
- */
-
-/**
- * Class: OpenLayers.Format.OWSCommon.v1_0_0
- * Parser for OWS Common version 1.0.0 which can be used by other parsers.
- * It is not intended to be used on its own.
- */
-OpenLayers.Format.OWSCommon.v1_0_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
-    
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        ows: "http://www.opengis.net/ows/1.0",
-        xlink: "http://www.w3.org/1999/xlink"
-    },    
-    
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "ows": OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"]
-    },
-
-    /**
-     * Property: writers
-     * As a compliment to the readers property, this structure contains public
-     *     writing functions grouped by namespace alias and named like the
-     *     node names they produce.
-     */
-    writers: {
-        "ows": OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"]
-    },
-    
-    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,50 @@
+/* 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/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_0_0
+ * Parser for OWS Common version 1.0.0 which can be used by other parsers.
+ * It is not intended to be used on its own.
+ */
+OpenLayers.Format.OWSCommon.v1_0_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.0",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"]
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "ows": OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"]
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
+
+});

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,64 +0,0 @@
-/* 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/Format/OWSCommon/v1.js
- */
-
-/**
- * Class: OpenLayers.Format.OWSCommon.v1_1_0
- * Parser for OWS Common version 1.1.0 which can be used by other parsers.
- * It is not intended to be used on its own.
- */
-OpenLayers.Format.OWSCommon.v1_1_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
-
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        ows: "http://www.opengis.net/ows/1.1",
-        xlink: "http://www.w3.org/1999/xlink"
-    },    
-    
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "ows": OpenLayers.Util.applyDefaults({
-            "AllowedValues": function(node, parameter) {
-                parameter.allowedValues = {};
-                this.readChildNodes(node, parameter.allowedValues);
-            },
-            "AnyValue": function(node, parameter) {
-                parameter.anyValue = true;
-            },
-            "Range": function(node, allowedValues) {
-                allowedValues.range = {};
-                this.readChildNodes(node, allowedValues.range);
-            },
-            "MinimumValue": function(node, range) {
-                range.minValue = this.getChildValue(node);
-            },
-            "MaximumValue": function(node, range) {
-                range.maxValue = this.getChildValue(node);
-            },
-            "Identifier": function(node, obj) {
-            	obj.identifier = this.getChildValue(node);
-            },
-            "SupportedCRS": function(node, obj) {
-                obj.supportedCRS = this.getChildValue(node);
-            }
-        }, OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])
-    },
-    
-    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSCommon/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,64 @@
+/* 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/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_1_0
+ * Parser for OWS Common version 1.1.0 which can be used by other parsers.
+ * It is not intended to be used on its own.
+ */
+OpenLayers.Format.OWSCommon.v1_1_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "ows": OpenLayers.Util.applyDefaults({
+            "AllowedValues": function(node, parameter) {
+                parameter.allowedValues = {};
+                this.readChildNodes(node, parameter.allowedValues);
+            },
+            "AnyValue": function(node, parameter) {
+                parameter.anyValue = true;
+            },
+            "Range": function(node, allowedValues) {
+                allowedValues.range = {};
+                this.readChildNodes(node, allowedValues.range);
+            },
+            "MinimumValue": function(node, range) {
+                range.minValue = this.getChildValue(node);
+            },
+            "MaximumValue": function(node, range) {
+                range.maxValue = this.getChildValue(node);
+            },
+            "Identifier": function(node, obj) {
+            	obj.identifier = this.getChildValue(node);
+            },
+            "SupportedCRS": function(node, obj) {
+                obj.supportedCRS = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
+
+});

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,589 +0,0 @@
-/* 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/Format/XML.js
- * @requires OpenLayers/Format/KML.js
- * @requires OpenLayers/Format/GML.js
- * @requires OpenLayers/Format/GML/v2.js
- * @requires OpenLayers/Format/SLD/v1_0_0.js
- * @requires OpenLayers/Format/OWSContext.js
- * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
- */
-
-/**
- * Class: OpenLayers.Format.OWSContext.v0_3_1
- * Read and write OWSContext version 0.3.1.
- *
- * Inherits from:
- *  - <OpenLayers.Format.XML>
- */
-OpenLayers.Format.OWSContext.v0_3_1 = OpenLayers.Class(OpenLayers.Format.XML, {
-    
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        owc: "http://www.opengis.net/ows-context",
-        gml: "http://www.opengis.net/gml",
-        kml: "http://www.opengis.net/kml/2.2",
-        ogc: "http://www.opengis.net/ogc",
-        ows: "http://www.opengis.net/ows",
-        sld: "http://www.opengis.net/sld",
-        xlink: "http://www.w3.org/1999/xlink",
-        xsi: "http://www.w3.org/2001/XMLSchema-instance"
-    },
-
-    /**
-     * Constant: VERSION
-     * {String} 0.3.1
-     */
-    VERSION: "0.3.1", 
-
-    /**
-     * Property: schemaLocation
-     * {String} Schema location
-     */
-    schemaLocation: "http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",
-
-    /**
-     * Property: defaultPrefix
-     * {String} Default namespace prefix to use.
-     */
-    defaultPrefix: "owc",
-
-    /**
-     * APIProperty: extractAttributes
-     * {Boolean} Extract attributes from GML.  Default is true.
-     */
-    extractAttributes: true,
-    
-    /**
-     * APIProperty: xy
-     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
-     * Changing is not recommended, a new Format should be instantiated.
-     */ 
-    xy: true, 
-
-    /**
-     * Property: regExes
-     * Compiled regular expressions for manipulating strings.
-     */
-    regExes: {
-        trimSpace: (/^\s*|\s*$/g),
-        removeSpace: (/\s*/g),
-        splitSpace: (/\s+/),
-        trimComma: (/\s*,\s*/g)
-    },
-
-    /**
-     * Property: featureNS
-     * {String} The namespace uri to use for writing InlineGeometry
-     */
-    featureNS: "http://mapserver.gis.umn.edu/mapserver",
-
-    /**
-     * Property: featureType
-     * {String} The name to use as the feature type when writing out
-     *     InlineGeometry
-     */
-    featureType: 'vector',
-              
-    /**
-     * Property: geometryName
-     * {String} The name to use for the geometry attribute when writing out
-     *     InlineGeometry
-     */
-    geometryName: 'geometry',
-
-    /**
-     * Property: nestingLayerLookup
-     * {Object} Hashtable lookup for nesting layer nodes. Used while writing 
-     *     the OWS context document. It is necessary to keep track of the 
-     *     nestingPaths for which nesting layer nodes have already been 
-     *     created, so (nesting) layer nodes are added to those nodes.
-     *
-     * For example:
-     *
-     *     If there are three layers with nestingPaths:
-     *         layer1.metadata.nestingPath = "a/b/"
-     *         layer2.metadata.nestingPath = "a/b/"
-     *         layer2.metadata.nestingPath = "a/c"
-     *
-     *     then a nesting layer node "a" should be created once and added 
-     *     to the resource list, a nesting layer node "b" should be created 
-     *     once and added under "a", and a nesting layer node "c" should be 
-     *     created and added under "a". The lookup paths for these nodes 
-     *     will be "a", "a/b", and "a/c" respectively.
-     */
-    nestingLayerLookup: null,
-
-    /**
-     * Constructor: OpenLayers.Format.OWSContext.v0_3_1
-     * Instances of this class are not created directly.  Use the
-     *     <OpenLayers.Format.OWSContext> constructor instead.
-     *
-     * Parameters:
-     * options - {Object} An optional object whose properties will be set on
-     *     this instance.
-     */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-        OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);
-    },
-
-    /**
-     * Method: setNestingPath
-     * Set the nestingPath property of the layer depending on the position
-     *     of the layer in hierarchy of layers.
-     *
-     * Parameters:
-     * l - {Object} An object that may have a layersContext array property.
-     * 
-     */
-    setNestingPath : function(l){
-        if(l.layersContext){
-            for (var i = 0, len = l.layersContext.length; i < len; i++) {
-                var layerContext = l.layersContext[i];
-                var nPath = [];
-                var nTitle = l.title || "";
-                if(l.metadata && l.metadata.nestingPath){
-                    nPath = l.metadata.nestingPath.slice();
-                }
-                if (nTitle != "") {
-                    nPath.push(nTitle);
-                }
-                layerContext.metadata.nestingPath = nPath;
-                if(layerContext.layersContext){
-                    this.setNestingPath(layerContext);
-                }
-            }
-        }
-    },
-
-    /**
-     * Function: decomposeNestingPath
-     * Takes a nestingPath like "a/b/c" and decomposes it into subpaths:
-     * "a", "a/b", "a/b/c"
-     *
-     * Parameters:
-     * nPath  - {Array} the nesting path
-     *
-     * Returns:
-     * Array({String}) Array with subpaths, or empty array if there is nothing
-     *     to decompose
-     */
-    decomposeNestingPath: function(nPath){
-        var a = [];
-        if (nPath instanceof Array) {
-            while (nPath.length > 0) {
-                a.push(nPath.slice());
-                nPath.pop();
-            }
-            a.reverse();
-        }
-        return a;
-    },
-
-    /**
-     * APIMethod: read
-     * Read OWS context data from a string or DOMElement, and return a list 
-     *     of layers. 
-     * 
-     * Parameters: 
-     * data - {String} or {DOMElement} data to read/parse.
-     *
-     * Returns:
-     * {Object} The context object with a flat layer list as a property named
-     *     layersContext.
-     */
-    read: function(data) {
-        if(typeof data == "string") {
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        if(data && data.nodeType == 9) {
-            data = data.documentElement;
-        }
-        var context = {};
-        this.readNode(data, context);
-        // since an OWSContext can be nested we need to go through this
-        // structure recursively      
-        this.setNestingPath({layersContext : context.layersContext});
-        // after nesting path has been set, create a flat list of layers
-        var layers = [];
-        this.processLayer(layers, context);
-        delete context.layersContext;
-        context.layersContext = layers;
-        return context;
-    },
-
-    /**
-     * Method: processLayer
-     * Recursive function to get back a flat list of layers from the hierarchic
-     *     layer structure.
-     *
-     * Parameters:
-     * layerArray - {Array({Object})} Array of layerContext objects
-     * layerContext - {Object} layerContext object
-     */
-    processLayer: function(layerArray, layer) {
-        if (layer.layersContext) {
-            for (var i=0, len = layer.layersContext.length; i<len; i++) {
-                var l = layer.layersContext[i];
-                layerArray.push(l);
-                if (l.layersContext) {
-                    this.processLayer(layerArray, l);
-                }
-            }
-        }
-    },
-
-    /**
-     * APIMethod: write
-     *
-     * Parameters:
-     * context - {Object} An object representing the map context.
-     * options - {Object} Optional object.
-     *
-     * Returns:
-     * {String} An OWS Context document string.
-     */
-    write: function(context, options) {
-        var name = "OWSContext";
-        this.nestingLayerLookup = {}; //start with empty lookup
-        options = options || {};
-        OpenLayers.Util.applyDefaults(options, context);
-        var root = this.writeNode(name, options);
-        this.nestingLayerLookup = null; //clear lookup
-        this.setAttributeNS(
-            root, this.namespaces["xsi"],
-            "xsi:schemaLocation", this.schemaLocation
-        );
-        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
-    }, 
-
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "kml": {
-            "Document": function(node, obj) {
-                obj.features = new OpenLayers.Format.KML(
-                    {kmlns: this.namespaces.kml, 
-                        extractStyles: true}).read(node);
-            }
-        },
-        "owc": { 
-            "OWSContext": function(node, obj) {
-                this.readChildNodes(node, obj);
-            }, 
-            "General": function(node, obj) {
-                this.readChildNodes(node, obj);
-            },
-            "ResourceList": function(node, obj) {
-                this.readChildNodes(node, obj);
-            },
-            "Layer": function(node, obj) {
-                var layerContext = {
-                    metadata: {},
-                    visibility: (node.getAttribute("hidden") != "1"),
-                    queryable: (node.getAttribute("queryable") == "1"),
-                    opacity: ((node.getAttribute("opacity") != null) ? 
-                        parseFloat(node.getAttribute("opacity")) : null),
-                    name: node.getAttribute("name"),
-                    /* A category layer is a dummy layer meant for creating
-                       hierarchies. It is not a physical layer in the 
-                       OpenLayers sense. The assumption we make here is that
-                       category layers do not have a name attribute */
-                    categoryLayer: (node.getAttribute("name") == null),
-                    formats: [],
-                    styles: []
-                };
-                if (!obj.layersContext) {
-                    obj.layersContext = [];
-                }
-                obj.layersContext.push(layerContext);
-                this.readChildNodes(node, layerContext);
-            },
-            "InlineGeometry": function(node, obj) {
-                obj.features = [];
-                var elements = this.getElementsByTagNameNS(node, 
-                    this.namespaces.gml, "featureMember");
-                var el;
-                if (elements.length >= 1) {
-                    el = elements[0];
-                }
-                if (el && el.firstChild) {
-                    var featurenode = (el.firstChild.nextSibling) ? 
-                        el.firstChild.nextSibling : el.firstChild;
-                    this.setNamespace("feature", featurenode.namespaceURI);
-                    this.featureType = featurenode.localName || 
-                        featurenode.nodeName.split(":").pop();
-                    this.readChildNodes(node, obj);
-                }
-            },
-            "Server": function(node, obj) {
-                // when having multiple Server types, we prefer WMS
-                if ((!obj.service && !obj.version) || 
-                    (obj.service != 
-                        OpenLayers.Format.Context.serviceTypes.WMS)) {
-                            obj.service = node.getAttribute("service");
-                            obj.version = node.getAttribute("version");
-                            this.readChildNodes(node, obj);
-                }
-            },
-            "Name": function(node, obj) {
-                obj.name = this.getChildValue(node);
-                this.readChildNodes(node, obj);
-            },
-            "Title": function(node, obj) {
-                obj.title = this.getChildValue(node);
-                this.readChildNodes(node, obj);
-            },
-            "StyleList": function(node, obj) {
-                this.readChildNodes(node, obj.styles);
-            },
-            "Style": function(node, obj) {
-                var style = {};
-                obj.push(style);
-                this.readChildNodes(node, style);
-            },
-            "LegendURL": function(node, obj) {
-                var legend = {};
-                obj.legend = legend;
-                this.readChildNodes(node, legend);
-            },
-            "OnlineResource": function(node, obj) {
-                obj.url = this.getAttributeNS(node, this.namespaces.xlink, 
-                    "href");
-                this.readChildNodes(node, obj);
-            }
-        },
-        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,
-        "gml": OpenLayers.Format.GML.v2.prototype.readers.gml,
-        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,
-        "feature": OpenLayers.Format.GML.v2.prototype.readers.feature
-    },
-
-    /**
-     * Property: writers
-     * As a compliment to the readers property, this structure contains public
-     *     writing functions grouped by namespace alias and named like the
-     *     node names they produce.
-     */
-    writers: {
-        "owc": {
-            "OWSContext": function(options) {
-                var node = this.createElementNSPlus("OWSContext", {
-                    attributes: {
-                        version: this.VERSION,
-                        id: options.id || OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")
-                    } 
-                }); 
-                this.writeNode("General", options, node);
-                this.writeNode("ResourceList", options, node);
-                return node; 
-            },
-            "General": function(options) {
-                var node = this.createElementNSPlus("General");
-                this.writeNode("ows:BoundingBox", options, node);
-                this.writeNode("ows:Title", options.title || 'OpenLayers OWSContext', node);
-                return node;
-            },
-            "ResourceList": function(options) {
-                var node = this.createElementNSPlus("ResourceList");
-                for (var i=0, len=options.layers.length; i<len; i++) {
-                    var layer = options.layers[i];
-                    var decomposedPath = this.decomposeNestingPath(layer.metadata.nestingPath);
-                    this.writeNode("_Layer", {layer: layer, subPaths: decomposedPath}, node);
-                }
-                return node;
-            },
-            "Server": function(options) {
-                var node = this.createElementNSPlus("Server", {attributes: {
-                    version: options.version,
-                    service: options.service }
-                });
-                this.writeNode("OnlineResource", options, node);
-                return node;
-            },
-            "OnlineResource": function(options) {
-                var node = this.createElementNSPlus("OnlineResource", {attributes: {
-                    "xlink:href": options.url }
-                });
-                return node;
-            },
-            "InlineGeometry": function(layer) {
-                var node = this.createElementNSPlus("InlineGeometry");
-                this.writeNode("gml:boundedBy", layer.getDataExtent(), node);
-                for (var i=0, len=layer.features.length; i<len; i++) {
-                    this.writeNode("gml:featureMember", layer.features[i], node);
-                }
-                return node;
-            },
-            "StyleList": function(styles) {
-                var node = this.createElementNSPlus("StyleList");
-                for (var i=0, len=styles.length; i<len; i++) {
-                    this.writeNode("Style", styles[i], node);
-                }
-                return node;
-            },
-            "Style": function(style) {
-                var node = this.createElementNSPlus("Style");
-                this.writeNode("Name", style, node);
-                this.writeNode("Title", style, node);
-                this.writeNode("LegendURL", style, node);
-                return node;
-            },
-            "Name": function(obj) {
-                var node = this.createElementNSPlus("Name", {
-                    value: obj.name });
-                return node;
-            },
-            "Title": function(obj) {
-                var node = this.createElementNSPlus("Title", {
-                    value: obj.title });
-                return node;
-            },
-            "LegendURL": function(style) {
-                var node = this.createElementNSPlus("LegendURL");
-                this.writeNode("OnlineResource", style.legend, node);
-                return node;
-            },
-            "_WMS": function(layer) {
-                var node = this.createElementNSPlus("Layer", {attributes: {
-                    name: layer.params.LAYERS,
-                    queryable: layer.queryable ? "1" : "0",
-                    hidden: layer.visibility ? "0" : "1",
-                    opacity: layer.opacity ? layer.opacity: null}
-                });
-                this.writeNode("ows:Title", layer.name, node);
-                this.writeNode("ows:OutputFormat", layer.params.FORMAT, node);
-                this.writeNode("Server", {service: 
-                    OpenLayers.Format.Context.serviceTypes.WMS,
-                    version: layer.params.VERSION, url: layer.url}, node);
-                if (layer.metadata.styles && layer.metadata.styles.length > 0) {
-                    this.writeNode("StyleList", layer.metadata.styles, node);
-                }
-                return node;
-            },
-            "_Layer": function(options) {
-                var layer, subPaths, node, title;
-                layer = options.layer;
-                subPaths = options.subPaths;
-                node = null;
-                title = null;
-                // subPaths is an array of an array
-                // recursively calling _Layer writer eats up subPaths, until a 
-                // real writer is called and nodes are returned.
-                if(subPaths.length > 0){
-                    var path = subPaths[0].join("/");
-                    var index = path.lastIndexOf("/");
-                    node = this.nestingLayerLookup[path];
-                    title = (index > 0)?path.substring(index + 1, path.length):path;
-                    if(!node){
-                        // category layer
-                        node = this.createElementNSPlus("Layer");
-                        this.writeNode("ows:Title", title, node);
-                        this.nestingLayerLookup[path] = node;
-                    }
-                    options.subPaths.shift();//remove a path after each call
-                    this.writeNode("_Layer", options, node);
-                    return node;
-                } else {
-                    // write out the actual layer
-                    if (layer instanceof OpenLayers.Layer.WMS) {
-                        node = this.writeNode("_WMS", layer);
-                    } else if (layer instanceof OpenLayers.Layer.Vector) {
-                        if (layer.protocol instanceof OpenLayers.Protocol.WFS.v1) {
-                            node = this.writeNode("_WFS", layer);
-                        } else if (layer.protocol instanceof OpenLayers.Protocol.HTTP) {
-                            if (layer.protocol.format instanceof OpenLayers.Format.GML) {
-                                layer.protocol.format.version = "2.1.2";
-                                node = this.writeNode("_GML", layer);
-                            } else if (layer.protocol.format instanceof OpenLayers.Format.KML) {
-                                layer.protocol.format.version = "2.2";
-                                node = this.writeNode("_KML", layer);
-                            }
-                        } else {
-                            // write out as inline GML since we have no idea
-                            // about the original Format
-                            this.setNamespace("feature", this.featureNS);
-                            node = this.writeNode("_InlineGeometry", layer);
-                        }
-                    }
-                    if (layer.options.maxScale) {
-                        this.writeNode("sld:MinScaleDenominator", 
-                            layer.options.maxScale, node);
-                    }
-                    if (layer.options.minScale) {
-                        this.writeNode("sld:MaxScaleDenominator", 
-                            layer.options.minScale, node);
-                    }
-                    this.nestingLayerLookup[layer.name] = node;
-                    return node;
-                }
-            },
-            "_WFS": function(layer) {
-                var node = this.createElementNSPlus("Layer", {attributes: {
-                    name: layer.protocol.featurePrefix + ":" + layer.protocol.featureType,
-                    hidden: layer.visibility ? "0" : "1" }
-                });
-                this.writeNode("ows:Title", layer.name, node);
-                this.writeNode("Server", {service: 
-                    OpenLayers.Format.Context.serviceTypes.WFS, 
-                    version: layer.protocol.version, 
-                    url: layer.protocol.url}, node);
-                return node;
-            },
-            "_InlineGeometry": function(layer) {
-                var node = this.createElementNSPlus("Layer", {attributes: {
-                    name: this.featureType,
-                    hidden: layer.visibility ? "0" : "1" }
-                });
-                this.writeNode("ows:Title", layer.name, node);
-                this.writeNode("InlineGeometry", layer, node);
-                return node;
-            },
-            "_GML": function(layer) {
-                var node = this.createElementNSPlus("Layer");
-                this.writeNode("ows:Title", layer.name, node);
-                this.writeNode("Server", {service: 
-                    OpenLayers.Format.Context.serviceTypes.GML, 
-                    url: layer.protocol.url, version: 
-                    layer.protocol.format.version}, node);
-                return node;
-            },
-            "_KML": function(layer) {
-                var node = this.createElementNSPlus("Layer");
-                this.writeNode("ows:Title", layer.name, node);
-                this.writeNode("Server", {service: 
-                    OpenLayers.Format.Context.serviceTypes.KML,
-                    version: layer.protocol.format.version, url: 
-                    layer.protocol.url}, node);
-                return node;
-            }
-        },
-        "gml": OpenLayers.Util.applyDefaults({
-            "boundedBy": function(bounds) {
-                var node = this.createElementNSPlus("gml:boundedBy");
-                this.writeNode("gml:Box", bounds, node);
-                return node;
-            }
-        }, OpenLayers.Format.GML.v2.prototype.writers.gml),
-        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,
-        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,
-        "feature": OpenLayers.Format.GML.v2.prototype.writers.feature
-    },
-    
-    CLASS_NAME: "OpenLayers.Format.OWSContext.v0_3_1" 
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext/v0_3_1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,589 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/KML.js
+ * @requires OpenLayers/Format/GML.js
+ * @requires OpenLayers/Format/GML/v2.js
+ * @requires OpenLayers/Format/SLD/v1_0_0.js
+ * @requires OpenLayers/Format/OWSContext.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext.v0_3_1
+ * Read and write OWSContext version 0.3.1.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OWSContext.v0_3_1 = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        owc: "http://www.opengis.net/ows-context",
+        gml: "http://www.opengis.net/gml",
+        kml: "http://www.opengis.net/kml/2.2",
+        ogc: "http://www.opengis.net/ogc",
+        ows: "http://www.opengis.net/ows",
+        sld: "http://www.opengis.net/sld",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 0.3.1
+     */
+    VERSION: "0.3.1", 
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",
+
+    /**
+     * Property: defaultPrefix
+     * {String} Default namespace prefix to use.
+     */
+    defaultPrefix: "owc",
+
+    /**
+     * APIProperty: extractAttributes
+     * {Boolean} Extract attributes from GML.  Default is true.
+     */
+    extractAttributes: true,
+    
+    /**
+     * APIProperty: xy
+     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+     * Changing is not recommended, a new Format should be instantiated.
+     */ 
+    xy: true, 
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Property: featureNS
+     * {String} The namespace uri to use for writing InlineGeometry
+     */
+    featureNS: "http://mapserver.gis.umn.edu/mapserver",
+
+    /**
+     * Property: featureType
+     * {String} The name to use as the feature type when writing out
+     *     InlineGeometry
+     */
+    featureType: 'vector',
+              
+    /**
+     * Property: geometryName
+     * {String} The name to use for the geometry attribute when writing out
+     *     InlineGeometry
+     */
+    geometryName: 'geometry',
+
+    /**
+     * Property: nestingLayerLookup
+     * {Object} Hashtable lookup for nesting layer nodes. Used while writing 
+     *     the OWS context document. It is necessary to keep track of the 
+     *     nestingPaths for which nesting layer nodes have already been 
+     *     created, so (nesting) layer nodes are added to those nodes.
+     *
+     * For example:
+     *
+     *     If there are three layers with nestingPaths:
+     *         layer1.metadata.nestingPath = "a/b/"
+     *         layer2.metadata.nestingPath = "a/b/"
+     *         layer2.metadata.nestingPath = "a/c"
+     *
+     *     then a nesting layer node "a" should be created once and added 
+     *     to the resource list, a nesting layer node "b" should be created 
+     *     once and added under "a", and a nesting layer node "c" should be 
+     *     created and added under "a". The lookup paths for these nodes 
+     *     will be "a", "a/b", and "a/c" respectively.
+     */
+    nestingLayerLookup: null,
+
+    /**
+     * Constructor: OpenLayers.Format.OWSContext.v0_3_1
+     * Instances of this class are not created directly.  Use the
+     *     <OpenLayers.Format.OWSContext> constructor instead.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);
+    },
+
+    /**
+     * Method: setNestingPath
+     * Set the nestingPath property of the layer depending on the position
+     *     of the layer in hierarchy of layers.
+     *
+     * Parameters:
+     * l - {Object} An object that may have a layersContext array property.
+     * 
+     */
+    setNestingPath : function(l){
+        if(l.layersContext){
+            for (var i = 0, len = l.layersContext.length; i < len; i++) {
+                var layerContext = l.layersContext[i];
+                var nPath = [];
+                var nTitle = l.title || "";
+                if(l.metadata && l.metadata.nestingPath){
+                    nPath = l.metadata.nestingPath.slice();
+                }
+                if (nTitle != "") {
+                    nPath.push(nTitle);
+                }
+                layerContext.metadata.nestingPath = nPath;
+                if(layerContext.layersContext){
+                    this.setNestingPath(layerContext);
+                }
+            }
+        }
+    },
+
+    /**
+     * Function: decomposeNestingPath
+     * Takes a nestingPath like "a/b/c" and decomposes it into subpaths:
+     * "a", "a/b", "a/b/c"
+     *
+     * Parameters:
+     * nPath  - {Array} the nesting path
+     *
+     * Returns:
+     * Array({String}) Array with subpaths, or empty array if there is nothing
+     *     to decompose
+     */
+    decomposeNestingPath: function(nPath){
+        var a = [];
+        if (nPath instanceof Array) {
+            while (nPath.length > 0) {
+                a.push(nPath.slice());
+                nPath.pop();
+            }
+            a.reverse();
+        }
+        return a;
+    },
+
+    /**
+     * APIMethod: read
+     * Read OWS context data from a string or DOMElement, and return a list 
+     *     of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} The context object with a flat layer list as a property named
+     *     layersContext.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var context = {};
+        this.readNode(data, context);
+        // since an OWSContext can be nested we need to go through this
+        // structure recursively      
+        this.setNestingPath({layersContext : context.layersContext});
+        // after nesting path has been set, create a flat list of layers
+        var layers = [];
+        this.processLayer(layers, context);
+        delete context.layersContext;
+        context.layersContext = layers;
+        return context;
+    },
+
+    /**
+     * Method: processLayer
+     * Recursive function to get back a flat list of layers from the hierarchic
+     *     layer structure.
+     *
+     * Parameters:
+     * layerArray - {Array({Object})} Array of layerContext objects
+     * layerContext - {Object} layerContext object
+     */
+    processLayer: function(layerArray, layer) {
+        if (layer.layersContext) {
+            for (var i=0, len = layer.layersContext.length; i<len; i++) {
+                var l = layer.layersContext[i];
+                layerArray.push(l);
+                if (l.layersContext) {
+                    this.processLayer(layerArray, l);
+                }
+            }
+        }
+    },
+
+    /**
+     * APIMethod: write
+     *
+     * Parameters:
+     * context - {Object} An object representing the map context.
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} An OWS Context document string.
+     */
+    write: function(context, options) {
+        var name = "OWSContext";
+        this.nestingLayerLookup = {}; //start with empty lookup
+        options = options || {};
+        OpenLayers.Util.applyDefaults(options, context);
+        var root = this.writeNode(name, options);
+        this.nestingLayerLookup = null; //clear lookup
+        this.setAttributeNS(
+            root, this.namespaces["xsi"],
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+    }, 
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "kml": {
+            "Document": function(node, obj) {
+                obj.features = new OpenLayers.Format.KML(
+                    {kmlns: this.namespaces.kml, 
+                        extractStyles: true}).read(node);
+            }
+        },
+        "owc": { 
+            "OWSContext": function(node, obj) {
+                this.readChildNodes(node, obj);
+            }, 
+            "General": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "ResourceList": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Layer": function(node, obj) {
+                var layerContext = {
+                    metadata: {},
+                    visibility: (node.getAttribute("hidden") != "1"),
+                    queryable: (node.getAttribute("queryable") == "1"),
+                    opacity: ((node.getAttribute("opacity") != null) ? 
+                        parseFloat(node.getAttribute("opacity")) : null),
+                    name: node.getAttribute("name"),
+                    /* A category layer is a dummy layer meant for creating
+                       hierarchies. It is not a physical layer in the 
+                       OpenLayers sense. The assumption we make here is that
+                       category layers do not have a name attribute */
+                    categoryLayer: (node.getAttribute("name") == null),
+                    formats: [],
+                    styles: []
+                };
+                if (!obj.layersContext) {
+                    obj.layersContext = [];
+                }
+                obj.layersContext.push(layerContext);
+                this.readChildNodes(node, layerContext);
+            },
+            "InlineGeometry": function(node, obj) {
+                obj.features = [];
+                var elements = this.getElementsByTagNameNS(node, 
+                    this.namespaces.gml, "featureMember");
+                var el;
+                if (elements.length >= 1) {
+                    el = elements[0];
+                }
+                if (el && el.firstChild) {
+                    var featurenode = (el.firstChild.nextSibling) ? 
+                        el.firstChild.nextSibling : el.firstChild;
+                    this.setNamespace("feature", featurenode.namespaceURI);
+                    this.featureType = featurenode.localName || 
+                        featurenode.nodeName.split(":").pop();
+                    this.readChildNodes(node, obj);
+                }
+            },
+            "Server": function(node, obj) {
+                // when having multiple Server types, we prefer WMS
+                if ((!obj.service && !obj.version) || 
+                    (obj.service != 
+                        OpenLayers.Format.Context.serviceTypes.WMS)) {
+                            obj.service = node.getAttribute("service");
+                            obj.version = node.getAttribute("version");
+                            this.readChildNodes(node, obj);
+                }
+            },
+            "Name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+                this.readChildNodes(node, obj);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+                this.readChildNodes(node, obj);
+            },
+            "StyleList": function(node, obj) {
+                this.readChildNodes(node, obj.styles);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                obj.push(style);
+                this.readChildNodes(node, style);
+            },
+            "LegendURL": function(node, obj) {
+                var legend = {};
+                obj.legend = legend;
+                this.readChildNodes(node, legend);
+            },
+            "OnlineResource": function(node, obj) {
+                obj.url = this.getAttributeNS(node, this.namespaces.xlink, 
+                    "href");
+                this.readChildNodes(node, obj);
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,
+        "gml": OpenLayers.Format.GML.v2.prototype.readers.gml,
+        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,
+        "feature": OpenLayers.Format.GML.v2.prototype.readers.feature
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "owc": {
+            "OWSContext": function(options) {
+                var node = this.createElementNSPlus("OWSContext", {
+                    attributes: {
+                        version: this.VERSION,
+                        id: options.id || OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")
+                    } 
+                }); 
+                this.writeNode("General", options, node);
+                this.writeNode("ResourceList", options, node);
+                return node; 
+            },
+            "General": function(options) {
+                var node = this.createElementNSPlus("General");
+                this.writeNode("ows:BoundingBox", options, node);
+                this.writeNode("ows:Title", options.title || 'OpenLayers OWSContext', node);
+                return node;
+            },
+            "ResourceList": function(options) {
+                var node = this.createElementNSPlus("ResourceList");
+                for (var i=0, len=options.layers.length; i<len; i++) {
+                    var layer = options.layers[i];
+                    var decomposedPath = this.decomposeNestingPath(layer.metadata.nestingPath);
+                    this.writeNode("_Layer", {layer: layer, subPaths: decomposedPath}, node);
+                }
+                return node;
+            },
+            "Server": function(options) {
+                var node = this.createElementNSPlus("Server", {attributes: {
+                    version: options.version,
+                    service: options.service }
+                });
+                this.writeNode("OnlineResource", options, node);
+                return node;
+            },
+            "OnlineResource": function(options) {
+                var node = this.createElementNSPlus("OnlineResource", {attributes: {
+                    "xlink:href": options.url }
+                });
+                return node;
+            },
+            "InlineGeometry": function(layer) {
+                var node = this.createElementNSPlus("InlineGeometry");
+                this.writeNode("gml:boundedBy", layer.getDataExtent(), node);
+                for (var i=0, len=layer.features.length; i<len; i++) {
+                    this.writeNode("gml:featureMember", layer.features[i], node);
+                }
+                return node;
+            },
+            "StyleList": function(styles) {
+                var node = this.createElementNSPlus("StyleList");
+                for (var i=0, len=styles.length; i<len; i++) {
+                    this.writeNode("Style", styles[i], node);
+                }
+                return node;
+            },
+            "Style": function(style) {
+                var node = this.createElementNSPlus("Style");
+                this.writeNode("Name", style, node);
+                this.writeNode("Title", style, node);
+                this.writeNode("LegendURL", style, node);
+                return node;
+            },
+            "Name": function(obj) {
+                var node = this.createElementNSPlus("Name", {
+                    value: obj.name });
+                return node;
+            },
+            "Title": function(obj) {
+                var node = this.createElementNSPlus("Title", {
+                    value: obj.title });
+                return node;
+            },
+            "LegendURL": function(style) {
+                var node = this.createElementNSPlus("LegendURL");
+                this.writeNode("OnlineResource", style.legend, node);
+                return node;
+            },
+            "_WMS": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: layer.params.LAYERS,
+                    queryable: layer.queryable ? "1" : "0",
+                    hidden: layer.visibility ? "0" : "1",
+                    opacity: layer.opacity ? layer.opacity: null}
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("ows:OutputFormat", layer.params.FORMAT, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.WMS,
+                    version: layer.params.VERSION, url: layer.url}, node);
+                if (layer.metadata.styles && layer.metadata.styles.length > 0) {
+                    this.writeNode("StyleList", layer.metadata.styles, node);
+                }
+                return node;
+            },
+            "_Layer": function(options) {
+                var layer, subPaths, node, title;
+                layer = options.layer;
+                subPaths = options.subPaths;
+                node = null;
+                title = null;
+                // subPaths is an array of an array
+                // recursively calling _Layer writer eats up subPaths, until a 
+                // real writer is called and nodes are returned.
+                if(subPaths.length > 0){
+                    var path = subPaths[0].join("/");
+                    var index = path.lastIndexOf("/");
+                    node = this.nestingLayerLookup[path];
+                    title = (index > 0)?path.substring(index + 1, path.length):path;
+                    if(!node){
+                        // category layer
+                        node = this.createElementNSPlus("Layer");
+                        this.writeNode("ows:Title", title, node);
+                        this.nestingLayerLookup[path] = node;
+                    }
+                    options.subPaths.shift();//remove a path after each call
+                    this.writeNode("_Layer", options, node);
+                    return node;
+                } else {
+                    // write out the actual layer
+                    if (layer instanceof OpenLayers.Layer.WMS) {
+                        node = this.writeNode("_WMS", layer);
+                    } else if (layer instanceof OpenLayers.Layer.Vector) {
+                        if (layer.protocol instanceof OpenLayers.Protocol.WFS.v1) {
+                            node = this.writeNode("_WFS", layer);
+                        } else if (layer.protocol instanceof OpenLayers.Protocol.HTTP) {
+                            if (layer.protocol.format instanceof OpenLayers.Format.GML) {
+                                layer.protocol.format.version = "2.1.2";
+                                node = this.writeNode("_GML", layer);
+                            } else if (layer.protocol.format instanceof OpenLayers.Format.KML) {
+                                layer.protocol.format.version = "2.2";
+                                node = this.writeNode("_KML", layer);
+                            }
+                        } else {
+                            // write out as inline GML since we have no idea
+                            // about the original Format
+                            this.setNamespace("feature", this.featureNS);
+                            node = this.writeNode("_InlineGeometry", layer);
+                        }
+                    }
+                    if (layer.options.maxScale) {
+                        this.writeNode("sld:MinScaleDenominator", 
+                            layer.options.maxScale, node);
+                    }
+                    if (layer.options.minScale) {
+                        this.writeNode("sld:MaxScaleDenominator", 
+                            layer.options.minScale, node);
+                    }
+                    this.nestingLayerLookup[layer.name] = node;
+                    return node;
+                }
+            },
+            "_WFS": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: layer.protocol.featurePrefix + ":" + layer.protocol.featureType,
+                    hidden: layer.visibility ? "0" : "1" }
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.WFS, 
+                    version: layer.protocol.version, 
+                    url: layer.protocol.url}, node);
+                return node;
+            },
+            "_InlineGeometry": function(layer) {
+                var node = this.createElementNSPlus("Layer", {attributes: {
+                    name: this.featureType,
+                    hidden: layer.visibility ? "0" : "1" }
+                });
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("InlineGeometry", layer, node);
+                return node;
+            },
+            "_GML": function(layer) {
+                var node = this.createElementNSPlus("Layer");
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.GML, 
+                    url: layer.protocol.url, version: 
+                    layer.protocol.format.version}, node);
+                return node;
+            },
+            "_KML": function(layer) {
+                var node = this.createElementNSPlus("Layer");
+                this.writeNode("ows:Title", layer.name, node);
+                this.writeNode("Server", {service: 
+                    OpenLayers.Format.Context.serviceTypes.KML,
+                    version: layer.protocol.format.version, url: 
+                    layer.protocol.url}, node);
+                return node;
+            }
+        },
+        "gml": OpenLayers.Util.applyDefaults({
+            "boundedBy": function(bounds) {
+                var node = this.createElementNSPlus("gml:boundedBy");
+                this.writeNode("gml:Box", bounds, node);
+                return node;
+            }
+        }, OpenLayers.Format.GML.v2.prototype.writers.gml),
+        "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,
+        "sld": OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,
+        "feature": OpenLayers.Format.GML.v2.prototype.writers.feature
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.OWSContext.v0_3_1" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/OWSContext.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/OWSContext.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,81 @@
+/* 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/Format/Context.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext
+ * Read and write OWS Context documents. OWS Context documents are a 
+ * preliminary OGC (Open Geospatial Consortium) standard for storing the 
+ * state of a web mapping application. In a way it is the successor to
+ * Web Map Context (WMC), since it is more generic and more types of layers
+ * can be stored. Also, nesting of layers is supported since version 0.3.1.
+ * For more information see: http://www.ogcnetwork.net/context
+ */
+OpenLayers.Format.OWSContext = OpenLayers.Class(OpenLayers.Format.Context,{
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "0.3.1".
+     */
+    defaultVersion: "0.3.1",
+    
+    /**
+     * Method: getParser
+     * Get the OWSContext parser given a version. Create a new parser if it does not
+     * already exist.
+     *
+     * Parameters:
+     * version - {String} The version of the parser.
+     *
+     * Returns:
+     * {<OpenLayers.Format.OWSContext>} An OWSContext parser.
+     */
+    getParser: function(version) {
+        var v = version || this.version || this.defaultVersion;
+        // 0.3.1 is backwards compatible with 0.3.0
+        if (v === "0.3.0") {
+            v = this.defaultVersion;
+        }
+        if(!this.parser || this.parser.VERSION != v) {
+            var format = OpenLayers.Format.OWSContext[
+                "v" + v.replace(/\./g, "_")
+            ];
+            if(!format) {
+                throw "Can't find a OWSContext parser for version " + v;
+            }
+            this.parser = new format(this.options);
+        }
+        return this.parser;
+    },
+
+    /**
+     * Method: toContext
+     * Create a context object free from layer given a map or a
+     * context object.
+     *
+     * Parameters:
+     * obj - {<OpenLayers.Map> | Object} The map or context.
+     *
+     * Returns:
+     * {Object} A context object.
+     */
+    toContext: function(obj) {
+        var context = {};
+        if(obj.CLASS_NAME == "OpenLayers.Map") {
+            context.bounds = obj.getExtent();
+            context.maxExtent = obj.maxExtent;
+            context.projection = obj.projection;
+            context.size = obj.getSize();
+            context.layers = obj.layers;
+        }
+        return context;
+    },
+
+    CLASS_NAME: "OpenLayers.Format.OWSContext" 
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -39,8 +40,29 @@
      * {String} Schema location for a particular minor version.
      */
     schemaLocation: null,
+    
+    /** 
+     * APIProperty: multipleSymbolizers
+     * {Boolean} Support multiple symbolizers per rule.  Default is false.  if
+     *     true, an OpenLayers.Style2 instance will be created to represent 
+     *     user styles instead of an OpenLayers.Style instace.  The 
+     *     OpenLayers.Style2 class allows collections of rules with multiple
+     *     symbolizers, but is not currently useful for client side rendering.
+     *     If multiple symbolizers is true, multiple FeatureTypeStyle elements
+     *     are preserved in reading/writing by setting symbolizer zIndex values.
+     *     In addition, the <defaultSymbolizer> property is ignored if 
+     *     multiple symbolizers are supported (defaults should be applied
+     *     when rendering).
+     */
+    multipleSymbolizers: false,
 
     /**
+     * Property: featureTypeCounter
+     * {Number} Private counter for multiple feature type styles.
+     */
+    featureTypeCounter: null,
+
+    /**
      * APIProperty: defaultSymbolizer.
      * {Object} A symbolizer with the SLD defaults.
      */
@@ -138,8 +160,15 @@
             },
             "UserStyle": function(node, layer) {
                 var obj = {defaultsPerSymbolizer: true, rules: []};
+                this.featureTypeCounter = -1;
                 this.readChildNodes(node, obj);
-                var style = new OpenLayers.Style(this.defaultSymbolizer, obj);
+                var style;
+                if (this.multipleSymbolizers) {
+                    delete obj.defaultsPerSymbolizer;
+                    style = new OpenLayers.Style2(obj);
+                } else {
+                    style = new OpenLayers.Style(this.defaultSymbolizer, obj);
+                }
                 layer.userStyles.push(style);
             },
             "IsDefault": function(node, style) {
@@ -148,18 +177,21 @@
                 }
             },
             "FeatureTypeStyle": function(node, style) {
-                // OpenLayers doesn't have a place for FeatureTypeStyle
-                // Name, Title, Abstract, FeatureTypeName, or
-                // SemanticTypeIdentifier so, we make a temporary object
-                // and later just use the Rule(s).
+                ++this.featureTypeCounter;
                 var obj = {
-                    rules: []
+                    rules: this.multipleSymbolizers ? style.rules : []
                 };
                 this.readChildNodes(node, obj);
-                style.rules = obj.rules;
+                if (!this.multipleSymbolizers) {
+                    style.rules = obj.rules;
+                }
             },
             "Rule": function(node, obj) {
-                var rule = new OpenLayers.Rule();
+                var config;
+                if (this.multipleSymbolizers) {
+                    config = {symbolizers: []};
+                }
+                var rule = new OpenLayers.Rule(config);
                 this.readChildNodes(node, rule);
                 obj.rules.push(rule);
             },
@@ -173,11 +205,18 @@
                 rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
             },
             "TextSymbolizer": function(node, rule) {
-                // OpenLayers doens't do painter's order, instead we extend
-                var symbolizer = rule.symbolizer["Text"] || {};
-                this.readChildNodes(node, symbolizer);
-                // in case it didn't exist before
-                rule.symbolizer["Text"] = symbolizer;
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Text(config)
+                    );
+                } else {
+                    rule.symbolizer["Text"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Text"]
+                    );
+                }
             },
             "Label": function(node, symbolizer) {
                 // only supporting literal or property name
@@ -210,26 +249,88 @@
                     symbolizer.haloRadius = radius;
                 }
             },
+            "RasterSymbolizer": function(node, rule) {
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Raster(config)
+                    );
+                } else {
+                    rule.symbolizer["Raster"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Raster"]
+                    );
+                }
+            },
+            "Geometry": function(node, obj) {
+                obj.geometry = {};
+                this.readChildNodes(node, obj.geometry);
+            },
+            "ColorMap": function(node, symbolizer) {
+                symbolizer.colorMap = [];
+                this.readChildNodes(node, symbolizer.colorMap);
+            },
+            "ColorMapEntry": function(node, colorMap) {
+                var q = node.getAttribute("quantity");
+                var o = node.getAttribute("opacity");
+                colorMap.push({
+                    color: node.getAttribute("color"),
+                    quantity: q !== null ? parseFloat(q) : undefined,
+                    label: node.getAttribute("label") || undefined,
+                    opacity: o !== null ? parseFloat(o) : undefined
+                });
+            },
             "LineSymbolizer": function(node, rule) {
-                // OpenLayers doesn't do painter's order, instead we extend
-                var symbolizer = rule.symbolizer["Line"] || {};
-                this.readChildNodes(node, symbolizer);
-                // in case it didn't exist before
-                rule.symbolizer["Line"] = symbolizer;
+                var config = {};
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Line(config)
+                    );
+                } else {
+                    rule.symbolizer["Line"] = OpenLayers.Util.applyDefaults(
+                        config, rule.symbolizer["Line"]
+                    );
+                }
             },
             "PolygonSymbolizer": function(node, rule) {
-                // OpenLayers doens't do painter's order, instead we extend
-                var symbolizer = rule.symbolizer["Polygon"] || {};
-                this.readChildNodes(node, symbolizer);
-                // in case it didn't exist before
-                rule.symbolizer["Polygon"] = symbolizer;
+                var config = {
+                    fill: false,
+                    stroke: false
+                };
+                if (!this.multipleSymbolizers) {
+                    config = rule.symbolizer["Polygon"] || config;
+                }
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Polygon(config)
+                    );
+                } else {
+                    rule.symbolizer["Polygon"] = config;
+                }
             },
             "PointSymbolizer": function(node, rule) {
-                // OpenLayers doens't do painter's order, instead we extend
-                var symbolizer = rule.symbolizer["Point"] || {};
-                this.readChildNodes(node, symbolizer);
-                // in case it didn't exist before
-                rule.symbolizer["Point"] = symbolizer;
+                var config = {
+                    fill: false,
+                    stroke: false,
+                    graphic: false
+                };
+                if (!this.multipleSymbolizers) {
+                    config = rule.symbolizer["Point"] || config;
+                }
+                this.readChildNodes(node, config);
+                if (this.multipleSymbolizers) {
+                    config.zIndex = this.featureTypeCounter;
+                    rule.symbolizers.push(
+                        new OpenLayers.Symbolizer.Point(config)
+                    );
+                } else {
+                    rule.symbolizer["Point"] = config;
+                }
             },
             "Stroke": function(node, symbolizer) {
                 symbolizer.stroke = true;
@@ -258,8 +359,8 @@
                 this.readChildNodes(node, graphic);
                 // directly properties with names that match symbolizer properties
                 var properties = [
-                    "strokeColor", "strokeWidth", "strokeOpacity",
-                    "strokeLinecap", "fillColor", "fillOpacity",
+                    "stroke", "strokeColor", "strokeWidth", "strokeOpacity",
+                    "strokeLinecap", "fill", "fillColor", "fillOpacity",
                     "graphicName", "rotation", "graphicFormat"
                 ];
                 var prop, value;
@@ -431,12 +532,18 @@
         "sld": {
             "StyledLayerDescriptor": function(sld) {
                 var root = this.createElementNSPlus(
-                    "StyledLayerDescriptor",
+                    "sld:StyledLayerDescriptor",
                     {attributes: {
                         "version": this.VERSION,
                         "xsi:schemaLocation": this.schemaLocation
                     }}
                 );
+
+                // For ArcGIS Server it is necessary to define this
+                // at the root level (see ticket:2166).
+                root.setAttribute("xmlns:ogc", this.namespaces.ogc);
+                root.setAttribute("xmlns:gml", this.namespaces.gml);
+
                 // add in optional name
                 if(sld.name) {
                     this.writeNode("Name", sld.name, root);
@@ -463,18 +570,18 @@
                 return root;
             },
             "Name": function(name) {
-                return this.createElementNSPlus("Name", {value: name});
+                return this.createElementNSPlus("sld:Name", {value: name});
             },
             "Title": function(title) {
-                return this.createElementNSPlus("Title", {value: title});
+                return this.createElementNSPlus("sld:Title", {value: title});
             },
             "Abstract": function(description) {
                 return this.createElementNSPlus(
-                    "Abstract", {value: description}
+                    "sld:Abstract", {value: description}
                 );
             },
             "NamedLayer": function(layer) {
-                var node = this.createElementNSPlus("NamedLayer");
+                var node = this.createElementNSPlus("sld:NamedLayer");
 
                 // add in required name
                 this.writeNode("Name", layer.name, node);
@@ -502,12 +609,12 @@
                 return node;
             },
             "NamedStyle": function(name) {
-                var node = this.createElementNSPlus("NamedStyle");
+                var node = this.createElementNSPlus("sld:NamedStyle");
                 this.writeNode("Name", name, node);
                 return node;
             },
             "UserStyle": function(style) {
-                var node = this.createElementNSPlus("UserStyle");
+                var node = this.createElementNSPlus("sld:UserStyle");
 
                 // add in optional name
                 if(style.name) {
@@ -528,17 +635,63 @@
                 }
                 
                 // add FeatureTypeStyles
-                this.writeNode("FeatureTypeStyle", style, node);
+                if (this.multipleSymbolizers && style.rules) {
+                    // group style objects by symbolizer zIndex
+                    var rulesByZ = {
+                        0: []
+                    };
+                    var zValues = [0];
+                    var rule, ruleMap, symbolizer, zIndex, clone;
+                    for (var i=0, ii=style.rules.length; i<ii; ++i) {
+                        rule = style.rules[i];
+                        if (rule.symbolizers) {
+                            ruleMap = {};
+                            for (var j=0, jj=rule.symbolizers.length; j<jj; ++j) {
+                                symbolizer = rule.symbolizers[j];
+                                zIndex = symbolizer.zIndex;
+                                if (!(zIndex in ruleMap)) {
+                                    clone = rule.clone();
+                                    clone.symbolizers = [];
+                                    ruleMap[zIndex] = clone;
+                                }
+                                ruleMap[zIndex].symbolizers.push(symbolizer.clone());
+                            }
+                            for (zIndex in ruleMap) {
+                                if (!(zIndex in rulesByZ)) {
+                                    zValues.push(zIndex);
+                                    rulesByZ[zIndex] = [];
+                                }
+                                rulesByZ[zIndex].push(ruleMap[zIndex]);
+                            }
+                        } else {
+                            // no symbolizers in rule
+                            rulesByZ[0].push(rule.clone());
+                        }
+                    }
+                    // write one FeatureTypeStyle per zIndex
+                    zValues.sort();
+                    var rules;
+                    for (var i=0, ii=zValues.length; i<ii; ++i) {
+                        rules = rulesByZ[zValues[i]];
+                        if (rules.length > 0) {
+                            clone = style.clone();
+                            clone.rules = rulesByZ[zValues[i]];
+                            this.writeNode("FeatureTypeStyle", clone, node);
+                        }
+                    }                    
+                } else {
+                    this.writeNode("FeatureTypeStyle", style, node);
+                }
                 
                 return node;
             },
             "IsDefault": function(bool) {
                 return this.createElementNSPlus(
-                    "IsDefault", {value: (bool) ? "1" : "0"}
+                    "sld:IsDefault", {value: (bool) ? "1" : "0"}
                 );
             },
             "FeatureTypeStyle": function(style) {
-                var node = this.createElementNSPlus("FeatureTypeStyle");
+                var node = this.createElementNSPlus("sld:FeatureTypeStyle");
                 
                 // OpenLayers currently stores no Name, Title, Abstract,
                 // FeatureTypeName, or SemanticTypeIdentifier information
@@ -552,7 +705,7 @@
                 return node;
             },
             "Rule": function(rule) {
-                var node = this.createElementNSPlus("Rule");
+                var node = this.createElementNSPlus("sld:Rule");
 
                 // add in optional name
                 if(rule.name) {
@@ -588,41 +741,52 @@
                     );
                 }
                 
-                // add in symbolizers (relies on geometry type keys)
-                var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
                 var type, symbolizer;
-                for(var i=0, len=types.length; i<len; ++i) {
-                    type = types[i];
-                    symbolizer = rule.symbolizer[type];
-                    if(symbolizer) {
+                if (this.multipleSymbolizers && rule.symbolizers) {
+                    var symbolizer;
+                    for (var i=0, ii=rule.symbolizers.length; i<ii; ++i) {
+                        symbolizer = rule.symbolizers[i];
+                        type = symbolizer.CLASS_NAME.split(".").pop();
                         this.writeNode(
                             type + "Symbolizer", symbolizer, node
                         );
                     }
+                } else {
+                    // add in symbolizers (relies on geometry type keys)
+                    var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
+                    for(var i=0, len=types.length; i<len; ++i) {
+                        type = types[i];
+                        symbolizer = rule.symbolizer[type];
+                        if(symbolizer) {
+                            this.writeNode(
+                                type + "Symbolizer", symbolizer, node
+                            );
+                        }
+                    }
                 }
                 return node;
 
             },
             "ElseFilter": function() {
-                return this.createElementNSPlus("ElseFilter");
+                return this.createElementNSPlus("sld:ElseFilter");
             },
             "MinScaleDenominator": function(scale) {
                 return this.createElementNSPlus(
-                    "MinScaleDenominator", {value: scale}
+                    "sld:MinScaleDenominator", {value: scale}
                 );
             },
             "MaxScaleDenominator": function(scale) {
                 return this.createElementNSPlus(
-                    "MaxScaleDenominator", {value: scale}
+                    "sld:MaxScaleDenominator", {value: scale}
                 );
             },
             "LineSymbolizer": function(symbolizer) {
-                var node = this.createElementNSPlus("LineSymbolizer");
+                var node = this.createElementNSPlus("sld:LineSymbolizer");
                 this.writeNode("Stroke", symbolizer, node);
                 return node;
             },
             "Stroke": function(symbolizer) {
-                var node = this.createElementNSPlus("Stroke");
+                var node = this.createElementNSPlus("sld:Stroke");
 
                 // GraphicFill here
                 // GraphicStroke here
@@ -649,17 +813,32 @@
                         node
                     );
                 }
+                if(symbolizer.strokeDashstyle != undefined && symbolizer.strokeDashstyle !== "solid") {
+                    // assumes valid stroke-dasharray value
+                    this.writeNode(
+                        "CssParameter", 
+                        {symbolizer: symbolizer, key: "strokeDashstyle"},
+                        node
+                    );
+                }
+                if(symbolizer.strokeLinecap != undefined) {
+                    this.writeNode(
+                        "CssParameter", 
+                        {symbolizer: symbolizer, key: "strokeLinecap"},
+                        node
+                    );
+                }
                 return node;
             },
             "CssParameter": function(obj) {
                 // not handling ogc:expressions for now
-                return this.createElementNSPlus("CssParameter", {
+                return this.createElementNSPlus("sld:CssParameter", {
                     attributes: {name: this.getCssProperty(obj.key)},
                     value: obj.symbolizer[obj.key]
                 });
             },
             "TextSymbolizer": function(symbolizer) {
-                var node = this.createElementNSPlus("TextSymbolizer");
+                var node = this.createElementNSPlus("sld:TextSymbolizer");
                 // add in optional Label
                 if(symbolizer.label != null) {
                     this.writeNode("Label", symbolizer.label, node);
@@ -685,7 +864,7 @@
                 return node;
             },
             "Font": function(symbolizer) {
-                var node = this.createElementNSPlus("Font");
+                var node = this.createElementNSPlus("sld:Font");
                 // add in CssParameters
                 if(symbolizer.fontFamily) {
                     this.writeNode(
@@ -720,7 +899,7 @@
             "Label": function(label) {
                 // only the simplest of ogc:expression handled
                 // {label: "some text and a ${propertyName}"}
-                var node = this.createElementNSPlus("Label");
+                var node = this.createElementNSPlus("sld:Label");
                 var tokens = label.split("${");
                 node.appendChild(this.createTextNode(tokens[0]));
                 var item, last;
@@ -746,7 +925,7 @@
                 return node;
             },
             "Halo": function(symbolizer) {
-                var node = this.createElementNSPlus("Halo");
+                var node = this.createElementNSPlus("sld:Halo");
                 if(symbolizer.haloRadius) {
                     this.writeNode("Radius", symbolizer.haloRadius, node);
                 }
@@ -759,26 +938,60 @@
                 return node;
             },
             "Radius": function(value) {
-                return node = this.createElementNSPlus("Radius", {
+                return this.createElementNSPlus("sld:Radius", {
                     value: value
                 });
             },
+            "RasterSymbolizer": function(symbolizer) {
+                var node = this.createElementNSPlus("sld:RasterSymbolizer");
+                if (symbolizer.geometry) {
+                    this.writeNode("Geometry", symbolizer.geometry, node);
+                }
+                if (symbolizer.opacity) {
+                    this.writeNode("Opacity", symbolizer.opacity, node);
+                }
+                if (symbolizer.colorMap) {
+                    this.writeNode("ColorMap", symbolizer.colorMap, node);
+                }
+                return node;
+            },
+            "Geometry": function(geometry) {
+                var node = this.createElementNSPlus("sld:Geometry");
+                if (geometry.property) {
+                    this.writeNode("ogc:PropertyName", geometry, node);
+                }
+                return node;
+            },
+            "ColorMap": function(colorMap) {
+                var node = this.createElementNSPlus("sld:ColorMap");
+                for (var i=0, len=colorMap.length; i<len; ++i) {
+                    this.writeNode("ColorMapEntry", colorMap[i], node);
+                }
+                return node;
+            },
+            "ColorMapEntry": function(colorMapEntry) {
+                var node = this.createElementNSPlus("sld:ColorMapEntry");
+                var a = colorMapEntry;
+                node.setAttribute("color", a.color);
+                a.opacity !== undefined && node.setAttribute("opacity",
+                    parseFloat(a.opacity));
+                a.quantity !== undefined && node.setAttribute("quantity",
+                    parseFloat(a.quantity));
+                a.label !== undefined && node.setAttribute("label", a.label);
+                return node;
+            },
             "PolygonSymbolizer": function(symbolizer) {
-                var node = this.createElementNSPlus("PolygonSymbolizer");
-                if(symbolizer.fillColor != undefined ||
-                   symbolizer.fillOpacity != undefined) {
+                var node = this.createElementNSPlus("sld:PolygonSymbolizer");
+                if(symbolizer.fill !== false) {
                     this.writeNode("Fill", symbolizer, node);
                 }
-                if(symbolizer.strokeWidth != undefined ||
-                   symbolizer.strokeColor != undefined ||
-                   symbolizer.strokeOpacity != undefined ||
-                   symbolizer.strokeDashstyle != undefined) {
+                if(symbolizer.stroke !== false) {
                     this.writeNode("Stroke", symbolizer, node);
                 }
                 return node;
             },
             "Fill": function(symbolizer) {
-                var node = this.createElementNSPlus("Fill");
+                var node = this.createElementNSPlus("sld:Fill");
                 
                 // GraphicFill here
                 
@@ -800,12 +1013,12 @@
                 return node;
             },
             "PointSymbolizer": function(symbolizer) {
-                var node = this.createElementNSPlus("PointSymbolizer");
+                var node = this.createElementNSPlus("sld:PointSymbolizer");
                 this.writeNode("Graphic", symbolizer, node);
                 return node;
             },
             "Graphic": function(symbolizer) {
-                var node = this.createElementNSPlus("Graphic");
+                var node = this.createElementNSPlus("sld:Graphic");
                 if(symbolizer.externalGraphic != undefined) {
                     this.writeNode("ExternalGraphic", symbolizer, node);
                 } else {
@@ -824,7 +1037,7 @@
                 return node;
             },
             "ExternalGraphic": function(symbolizer) {
-                var node = this.createElementNSPlus("ExternalGraphic");
+                var node = this.createElementNSPlus("sld:ExternalGraphic");
                 this.writeNode(
                     "OnlineResource", symbolizer.externalGraphic, node
                 );
@@ -834,36 +1047,40 @@
                 return node;
             },
             "Mark": function(symbolizer) {
-                var node = this.createElementNSPlus("Mark");
+                var node = this.createElementNSPlus("sld:Mark");
                 if(symbolizer.graphicName) {
                     this.writeNode("WellKnownName", symbolizer.graphicName, node);
                 }
-                this.writeNode("Fill", symbolizer, node);
-                this.writeNode("Stroke", symbolizer, node);
+                if (symbolizer.fill !== false) {
+                    this.writeNode("Fill", symbolizer, node);
+                }
+                if (symbolizer.stroke !== false) {
+                    this.writeNode("Stroke", symbolizer, node);
+                }
                 return node;
             },
             "WellKnownName": function(name) {
-                return this.createElementNSPlus("WellKnownName", {
+                return this.createElementNSPlus("sld:WellKnownName", {
                     value: name
                 });
             },
             "Opacity": function(value) {
-                return this.createElementNSPlus("Opacity", {
+                return this.createElementNSPlus("sld:Opacity", {
                     value: value
                 });
             },
             "Size": function(value) {
-                return this.createElementNSPlus("Size", {
+                return this.createElementNSPlus("sld:Size", {
                     value: value
                 });
             },
             "Rotation": function(value) {
-                return this.createElementNSPlus("Rotation", {
+                return this.createElementNSPlus("sld:Rotation", {
                     value: value
                 });
             },
             "OnlineResource": function(href) {
-                return this.createElementNSPlus("OnlineResource", {
+                return this.createElementNSPlus("sld:OnlineResource", {
                     attributes: {
                         "xlink:type": "simple",
                         "xlink:href": href
@@ -871,7 +1088,7 @@
                 });
             },
             "Format": function(format) {
-                return this.createElementNSPlus("Format", {
+                return this.createElementNSPlus("sld:Format", {
                     value: format
                 });
             }
@@ -880,4 +1097,4 @@
     
     CLASS_NAME: "OpenLayers.Format.SLD.v1" 
 
-});
+});
\ No newline at end of file

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SLD.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Format/XML.js

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,158 +0,0 @@
-/* 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/Format/SOSCapabilities.js
- * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
- * @requires OpenLayers/Format/GML/v3.js
- */
-
-/**
- * Class: OpenLayers.Format.SOSCapabilities.v1_0_0
- * Read SOS Capabilities version 1.0.0.
- * 
- * Inherits from:
- *  - <OpenLayers.Format.SOSCapabilities>
- */
-OpenLayers.Format.SOSCapabilities.v1_0_0 = OpenLayers.Class(
-    OpenLayers.Format.SOSCapabilities, {
-
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        ows: "http://www.opengis.net/ows/1.1",
-        sos: "http://www.opengis.net/sos/1.0",
-        gml: "http://www.opengis.net/gml",
-        xlink: "http://www.w3.org/1999/xlink"
-    },
-
-    /**
-     * Property: regExes
-     * Compiled regular expressions for manipulating strings.
-     */
-    regExes: {
-        trimSpace: (/^\s*|\s*$/g),
-        removeSpace: (/\s*/g),
-        splitSpace: (/\s+/),
-        trimComma: (/\s*,\s*/g)
-    },
-    
-    /**
-     * Constructor: OpenLayers.Format.SOSCapabilities.v1_0_0
-     * Create a new parser for SOS capabilities version 1.0.0. 
-     *
-     * Parameters:
-     * options - {Object} An optional object whose properties will be set on
-     *     this instance.
-     */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-        this.options = options;
-    },
-
-    /**
-     * APIMethod: read
-     * Read capabilities data from a string, and return info about the SOS.
-     * 
-     * Parameters: 
-     * data - {String} or {DOMElement} data to read/parse.
-     *
-     * Returns:
-     * {Object} Information about the SOS service.
-     */
-    read: function(data) {
-        if(typeof data == "string") {
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        if(data && data.nodeType == 9) {
-            data = data.documentElement;
-        }
-        var capabilities = {};
-        this.readNode(data, capabilities);
-        return capabilities;
-    },
-
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {
-        "gml": OpenLayers.Util.applyDefaults({
-            "name": function(node, obj) {
-                obj.name = this.getChildValue(node);
-            },
-            "TimePeriod": function(node, obj) {
-                obj.timePeriod = {};
-                this.readChildNodes(node, obj.timePeriod);
-            },
-            "beginPosition": function(node, timePeriod) {
-                timePeriod.beginPosition = this.getChildValue(node);
-            },
-            "endPosition": function(node, timePeriod) {
-                timePeriod.endPosition = this.getChildValue(node);
-            }
-        }, OpenLayers.Format.GML.v3.prototype.readers["gml"]),
-        "sos": {
-            "Capabilities": function(node, obj) {
-                this.readChildNodes(node, obj);
-            },
-            "Contents": function(node, obj) {
-                obj.contents = {};
-                this.readChildNodes(node, obj.contents);
-            },
-            "ObservationOfferingList": function(node, contents) {
-                contents.offeringList = {};
-                this.readChildNodes(node, contents.offeringList);
-            },
-            "ObservationOffering": function(node, offeringList) {
-                var id = this.getAttributeNS(node, this.namespaces.gml, "id");
-                offeringList[id] = {
-                    procedures: [],
-                    observedProperties: [],
-                    featureOfInterestIds: [],
-                    responseFormats: [],
-                    resultModels: [],
-                    responseModes: []
-                };
-                this.readChildNodes(node, offeringList[id]);
-            },
-            "time": function(node, offering) {
-                offering.time = {};
-                this.readChildNodes(node, offering.time);
-            },
-            "procedure": function(node, offering) {
-                offering.procedures.push(this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href"));
-            },
-            "observedProperty": function(node, offering) {
-                offering.observedProperties.push(this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href"));
-            },
-            "featureOfInterest": function(node, offering) {
-                offering.featureOfInterestIds.push(this.getAttributeNS(node, 
-                    this.namespaces.xlink, "href"));
-            },
-            "responseFormat": function(node, offering) {
-                offering.responseFormats.push(this.getChildValue(node));
-            },
-            "resultModel": function(node, offering) {
-                offering.resultModels.push(this.getChildValue(node));
-            },
-            "responseMode": function(node, offering) {
-                offering.responseModes.push(this.getChildValue(node));;
-            }
-        },
-        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
-    },    
-    
-    CLASS_NAME: "OpenLayers.Format.SOSCapabilities.v1_0_0" 
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,158 @@
+/* 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/Format/SOSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSCapabilities.v1_0_0
+ * Read SOS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.SOSCapabilities>
+ */
+OpenLayers.Format.SOSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.SOSCapabilities, {
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        sos: "http://www.opengis.net/sos/1.0",
+        gml: "http://www.opengis.net/gml",
+        xlink: "http://www.w3.org/1999/xlink"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.SOSCapabilities.v1_0_0
+     * Create a new parser for SOS capabilities version 1.0.0. 
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return info about the SOS.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the SOS service.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        return capabilities;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "gml": OpenLayers.Util.applyDefaults({
+            "name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "TimePeriod": function(node, obj) {
+                obj.timePeriod = {};
+                this.readChildNodes(node, obj.timePeriod);
+            },
+            "beginPosition": function(node, timePeriod) {
+                timePeriod.beginPosition = this.getChildValue(node);
+            },
+            "endPosition": function(node, timePeriod) {
+                timePeriod.endPosition = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.GML.v3.prototype.readers["gml"]),
+        "sos": {
+            "Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Contents": function(node, obj) {
+                obj.contents = {};
+                this.readChildNodes(node, obj.contents);
+            },
+            "ObservationOfferingList": function(node, contents) {
+                contents.offeringList = {};
+                this.readChildNodes(node, contents.offeringList);
+            },
+            "ObservationOffering": function(node, offeringList) {
+                var id = this.getAttributeNS(node, this.namespaces.gml, "id");
+                offeringList[id] = {
+                    procedures: [],
+                    observedProperties: [],
+                    featureOfInterestIds: [],
+                    responseFormats: [],
+                    resultModels: [],
+                    responseModes: []
+                };
+                this.readChildNodes(node, offeringList[id]);
+            },
+            "time": function(node, offering) {
+                offering.time = {};
+                this.readChildNodes(node, offering.time);
+            },
+            "procedure": function(node, offering) {
+                offering.procedures.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "observedProperty": function(node, offering) {
+                offering.observedProperties.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "featureOfInterest": function(node, offering) {
+                offering.featureOfInterestIds.push(this.getAttributeNS(node, 
+                    this.namespaces.xlink, "href"));
+            },
+            "responseFormat": function(node, offering) {
+                offering.responseFormats.push(this.getChildValue(node));
+            },
+            "resultModel": function(node, offering) {
+                offering.resultModels.push(this.getChildValue(node));
+            },
+            "responseMode": function(node, offering) {
+                offering.responseModes.push(this.getChildValue(node));;
+            }
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },    
+    
+    CLASS_NAME: "OpenLayers.Format.SOSCapabilities.v1_0_0" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/SOSCapabilities.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSCapabilities.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,83 @@
+/* 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/Format/XML.js
+ */
+ 
+/**
+ * Class: OpenLayers.Format.SOSCapabilities
+ * Read SOS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSCapabilities = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * APIProperty: version
+     * {String} Specify a version string if one is known.
+     */
+    version: null,
+
+    /**
+     * Property: parser
+     * {<OpenLayers.Format>} A cached versioned format used for reading.
+     */
+    parser: null,     
+
+    /**
+     * Constructor: OpenLayers.Format.SOSCapabilities
+     * Create a new parser for SOS capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return information about
+     * the service (offering and observedProperty mostly).
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Info about the SOS
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var version = this.version || root.getAttribute("version") || this.defaultVersion;
+        if(!this.parser || this.parser.version !== version) {
+            var constr = OpenLayers.Format.SOSCapabilities[
+                "v" + version.replace(/\./g, "_")
+            ];
+            if(!constr) {
+                throw "Can't find a SOS capabilities parser for version " + version;
+            }
+            var parser = new constr(this.options);
+        }
+        var capabilities = parser.read(data);
+        capabilities.version = version;
+        return capabilities; 
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.SOSCapabilities" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,193 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetFeatureOfInterest
+ * Read and write SOS GetFeatureOfInterest. This is used to get to
+ * the location of the features (stations). The stations can have 1 or more
+ * sensors.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetFeatureOfInterest = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        sos: "http://www.opengis.net/sos/1.0",
+        gml: "http://www.opengis.net/gml",
+        sa: "http://www.opengis.net/sampling/1.0",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "sos",
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+    
+    /**
+     * Constructor: OpenLayers.Format.SOSGetFeatureOfInterest
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Parse a GetFeatureOfInterest response and return an array of features
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array(<OpenLayers.Feature.Vector>)} An array of features. 
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+
+        var info = {features: []};
+        this.readNode(data, info);
+       
+        var features = [];
+        for (var i=0, len=info.features.length; i<len; i++) {
+            var container = info.features[i];
+            // reproject features if needed
+            if(this.internalProjection && this.externalProjection &&
+                container.components[0]) {
+                    container.components[0].transform(
+                        this.externalProjection, this.internalProjection
+                    );
+            }             
+            var feature = new OpenLayers.Feature.Vector(
+                container.components[0], container.attributes);
+            features.push(feature);
+        }
+        return features;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "sa": {
+            "SamplingPoint": function(node, obj) {
+                // sampling point can also be without a featureMember if 
+                // there is only 1
+                if (!obj.attributes) {
+                    var feature = {attributes: {}};
+                    obj.features.push(feature);
+                    obj = feature;
+                }
+                obj.attributes.id = this.getAttributeNS(node, 
+                    this.namespaces.gml, "id");
+                this.readChildNodes(node, obj);
+            },
+            "position": function (node, obj) {
+                this.readChildNodes(node, obj);
+            }
+        },
+        "gml": OpenLayers.Util.applyDefaults({
+            "FeatureCollection": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "featureMember": function(node, obj) {
+                var feature = {attributes: {}};
+                obj.features.push(feature);
+                this.readChildNodes(node, feature);
+            },
+            "name": function(node, obj) {
+                obj.attributes.name = this.getChildValue(node);
+            },
+            "pos": function(node, obj) {
+                // we need to parse the srsName to get to the 
+                // externalProjection, that's why we cannot use
+                // GML v3 for this
+                if (!this.externalProjection) {
+                    this.externalProjection = new OpenLayers.Projection(
+                        node.getAttribute("srsName"));
+                }
+             OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(
+                    this, [node, obj]);
+            }
+        }, OpenLayers.Format.GML.v3.prototype.readers.gml)
+    },
+    
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "sos": {
+            "GetFeatureOfInterest": function(options) {
+                var node = this.createElementNSPlus("GetFeatureOfInterest", {
+                    attributes: {
+                        version: this.VERSION,
+                        service: 'SOS',
+                        "xsi:schemaLocation": this.schemaLocation
+                    } 
+                }); 
+                for (var i=0, len=options.fois.length; i<len; i++) {
+                    this.writeNode("FeatureOfInterestId", {foi: options.fois[i]}, node);
+                }
+                return node; 
+            },
+            "FeatureOfInterestId": function(options) {
+                var node = this.createElementNSPlus("FeatureOfInterestId", {value: options.foi});
+                return node;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.SOSGetFeatureOfInterest" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetObservation.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/SOSGetObservation.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetObservation.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/SOSGetObservation.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,305 @@
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetObservation
+ * Read and write SOS GetObersation (to get the actual values from a sensor) 
+ *     version 1.0.0
+ *
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetObservation = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows",
+        gml: "http://www.opengis.net/gml",
+        sos: "http://www.opengis.net/sos/1.0",
+        ogc: "http://www.opengis.net/ogc",
+        om: "http://www.opengis.net/om/1.0",
+        sa: "http://www.opengis.net/sampling/1.0",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: regExes
+     * Compiled regular expressions for manipulating strings.
+     */
+    regExes: {
+        trimSpace: (/^\s*|\s*$/g),
+        removeSpace: (/\s*/g),
+        splitSpace: (/\s+/),
+        trimComma: (/\s*,\s*/g)
+    },
+
+    /**
+     * Constant: VERSION
+     * {String} 1.0.0
+     */
+    VERSION: "1.0.0",
+
+    /**
+     * Property: schemaLocation
+     * {String} Schema location
+     */
+    schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "sos",
+
+    /**
+     * Constructor: OpenLayers.Format.SOSGetObservation
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * Method: read
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} An object containing the measurements
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var info = {measurements: [], observations: []};
+        this.readNode(data, info);
+        return info;
+    },
+
+    /**
+     * Method: write
+     *
+     * Parameters:
+     * options - {Object} Optional object.
+     *
+     * Returns:
+     * {String} An SOS GetObservation request XML string.
+     */
+    write: function(options) {
+        var node = this.writeNode("sos:GetObservation", options);
+        node.setAttribute("xmlns:om", this.namespaces.om);
+        node.setAttribute("xmlns:ogc", this.namespaces.ogc);
+        this.setAttributeNS(
+            node, this.namespaces.xsi,
+            "xsi:schemaLocation", this.schemaLocation
+        );
+        return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+    }, 
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "om": {
+            "ObservationCollection": function(node, obj) {
+                obj.id = this.getAttributeNS(node, this.namespaces.gml, "id");
+                this.readChildNodes(node, obj);
+            },
+            "member": function(node, observationCollection) {
+                this.readChildNodes(node, observationCollection);
+            },
+            "Measurement": function(node, observationCollection) {
+                var measurement = {};
+                observationCollection.measurements.push(measurement);
+                this.readChildNodes(node, measurement);
+            },
+            "Observation": function(node, observationCollection) {
+                var observation = {};
+                observationCollection.observations.push(observation);
+                this.readChildNodes(node, observation);
+            },
+            "samplingTime": function(node, measurement) {
+                var samplingTime = {};
+                measurement.samplingTime = samplingTime;
+                this.readChildNodes(node, samplingTime);
+            },
+            "observedProperty": function(node, measurement) {
+                measurement.observedProperty = 
+                    this.getAttributeNS(node, this.namespaces.xlink, "href");
+                this.readChildNodes(node, measurement);
+            },
+            "procedure": function(node, measurement) {
+                measurement.procedure = 
+                    this.getAttributeNS(node, this.namespaces.xlink, "href");
+                this.readChildNodes(node, measurement);
+            },
+            "featureOfInterest": function(node, observation) {
+                var foi = {features: []};
+                observation.fois = [];
+                observation.fois.push(foi);
+                this.readChildNodes(node, foi);
+                // postprocessing to get actual features
+                var features = [];
+                for (var i=0, len=foi.features.length; i<len; i++) {
+                    var feature = foi.features[i];
+                    features.push(new OpenLayers.Feature.Vector(
+                        feature.components[0], feature.attributes));
+                }
+                foi.features = features;
+            },
+            "result": function(node, measurement) {
+                var result = {};
+                measurement.result = result;
+                if (this.getChildValue(node) !== '') {
+                    result.value = this.getChildValue(node);
+                    result.uom = node.getAttribute("uom");
+                } else {
+                    this.readChildNodes(node, result);
+                }
+            }
+        },
+        "sa": OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.sa,
+        "gml": OpenLayers.Util.applyDefaults({
+            "TimeInstant": function(node, samplingTime) {
+               var timeInstant = {};
+                samplingTime.timeInstant = timeInstant;
+                this.readChildNodes(node, timeInstant);
+            },
+            "timePosition": function(node, timeInstant) {
+                timeInstant.timePosition = this.getChildValue(node);
+            }
+        }, OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.gml)
+    },
+
+    /**
+     * Property: writers
+     * As a compliment to the readers property, this structure contains public
+     *     writing functions grouped by namespace alias and named like the
+     *     node names they produce.
+     */
+    writers: {
+        "sos": {
+            "GetObservation": function(options) {
+                var node = this.createElementNSPlus("GetObservation", {
+                    attributes: {
+                        version: this.VERSION,
+                        service: 'SOS'
+                    } 
+                }); 
+                this.writeNode("offering", options, node);
+                if (options.eventTime) {
+                    this.writeNode("eventTime", options, node);
+                }
+                for (var procedure in options.procedures) {
+                    this.writeNode("procedure", options.procedures[procedure], node);
+                }
+                for (var observedProperty in options.observedProperties) {
+                    this.writeNode("observedProperty", options.observedProperties[observedProperty], node);
+                }
+                if (options.foi) {
+                    this.writeNode("featureOfInterest", options.foi, node);
+                }
+                this.writeNode("responseFormat", options, node);
+                if (options.resultModel) {
+                    this.writeNode("resultModel", options, node);
+                }
+                if (options.responseMode) {
+                    this.writeNode("responseMode", options, node);
+                }
+                return node; 
+            },
+            "featureOfInterest": function(foi) {
+                var node = this.createElementNSPlus("featureOfInterest");
+                this.writeNode("ObjectID", foi.objectId, node);
+                return node;
+            },
+            "ObjectID": function(options) {
+                return this.createElementNSPlus("ObjectID",
+                    {value: options});
+            },
+            "responseFormat": function(options) {
+                return this.createElementNSPlus("responseFormat", 
+                    {value: options.responseFormat});
+            },
+            "procedure": function(procedure) {
+                return this.createElementNSPlus("procedure", 
+                    {value: procedure});
+            },
+            "offering": function(options) {
+                return this.createElementNSPlus("offering", {value: 
+                    options.offering});
+            },
+            "observedProperty": function(observedProperty) {
+                return this.createElementNSPlus("observedProperty", 
+                    {value: observedProperty});
+            },
+            "eventTime": function(options) {
+                var node = this.createElementNSPlus("eventTime");
+                if (options.eventTime === 'latest') {
+                    this.writeNode("ogc:TM_Equals", options, node);
+                }
+                return node;
+            },
+            "resultModel": function(options) {
+                return this.createElementNSPlus("resultModel", {value: 
+                    options.resultModel});
+            },
+            "responseMode": function(options) {
+                return this.createElementNSPlus("responseMode", {value: 
+                    options.responseMode});
+            }
+        },
+        "ogc": {
+            "TM_Equals": function(options) {
+                var node = this.createElementNSPlus("ogc:TM_Equals");
+                this.writeNode("ogc:PropertyName", {property: 
+                    "urn:ogc:data:time:iso8601"}, node);
+                if (options.eventTime === 'latest') {
+                    this.writeNode("gml:TimeInstant", {value: 'latest'}, node);
+                }
+                return node;
+            },
+            "PropertyName": function(options) {
+                return this.createElementNSPlus("ogc:PropertyName", 
+                    {value: options.property});
+            }
+        },
+        "gml": {
+            "TimeInstant": function(options) {
+                var node = this.createElementNSPlus("gml:TimeInstant");
+                this.writeNode("gml:timePosition", options, node);
+                return node;
+            },
+            "timePosition": function(options) {
+                var node = this.createElementNSPlus("gml:timePosition", 
+                    {value: options.value});
+                return node;
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.SOSGetObservation" 
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/Text.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/Text.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/Text.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Feature/Vector.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WFSCapabilities.js
  */
@@ -88,7 +93,11 @@
     read_cap_Name: function(obj, node) {
         var name = this.getChildValue(node);
         if(name) {
-            obj.name = name;
+            var parts = name.split(":");
+            obj.name = parts.pop();
+            if(parts.length > 0) {
+                obj.featureNS = this.lookupNamespaceURI(node, parts[0]);
+            }
         }
     },
 
@@ -114,4 +123,4 @@
     
     CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1" 
 
-});
\ No newline at end of file
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WFSCapabilities/v1.js
  */
@@ -25,7 +30,128 @@
             this, [options]
         );
     },
+    
+    /**
+     * Method: read_cap_Service
+     */
+    read_cap_Service: function(capabilities, node) {
+        var service = {};
+        this.runChildNodes(service, node);
+        capabilities.service = service;
+    },
 
+    /**
+     * Method: read_cap_Fees
+     */
+    read_cap_Fees: function(service, node) {
+        var fees = this.getChildValue(node);
+        if (fees && fees.toLowerCase() != "none") {
+            service.fees = fees;
+        }
+    },
+
+    /**
+     * Method: read_cap_AccessConstraints
+     */
+    read_cap_AccessConstraints: function(service, node) {
+        var constraints = this.getChildValue(node);
+        if (constraints && constraints.toLowerCase() != "none") {
+            service.accessConstraints = constraints;
+        }
+    },
+    
+    /**
+     * Method: read_cap_OnlineResource
+     */
+    read_cap_OnlineResource: function(service, node) {
+        var onlineResource = this.getChildValue(node);
+        if (onlineResource && onlineResource.toLowerCase() != "none") {
+            service.onlineResource = onlineResource;
+        }
+    },
+    
+    /**
+     * Method: read_cap_Keywords
+     */
+    read_cap_Keywords: function(service, node) {
+        var keywords = this.getChildValue(node);
+        if (keywords && keywords.toLowerCase() != "none") {
+            service.keywords = keywords.split(', ');
+        }
+    },
+    
+    /**
+     * Method: read_cap_Capability
+     */
+    read_cap_Capability: function(capabilities, node) {
+        var capability = {};
+        this.runChildNodes(capability, node);
+        capabilities.capability = capability;
+    },
+    
+    /**
+     * Method: read_cap_Request
+     */
+    read_cap_Request: function(obj, node) {
+        var request = {};
+        this.runChildNodes(request, node);
+        obj.request = request;
+    },
+    
+    /**
+     * Method: read_cap_GetFeature
+     */
+    read_cap_GetFeature: function(request, node) {
+        var getfeature = {
+            href: {}, // DCPType
+            formats: [] // ResultFormat
+        };
+        this.runChildNodes(getfeature, node);
+        request.getfeature = getfeature;
+    },
+    
+    /**
+     * Method: read_cap_ResultFormat
+     */
+    read_cap_ResultFormat: function(obj, node) {
+        var children = node.childNodes;
+        var childNode;
+        for(var i=0; i<children.length; i++) {
+            childNode = children[i];
+            if(childNode.nodeType == 1) {
+                obj.formats.push(childNode.nodeName);
+            }
+        }
+    },
+    
+    /**
+     * Method: read_cap_DCPType
+     */
+    read_cap_DCPType: function(obj, node) {
+        this.runChildNodes(obj, node);
+    },
+    
+    /**
+     * Method: read_cap_HTTP
+     */
+    read_cap_HTTP: function(obj, node) {
+        this.runChildNodes(obj.href, node);
+    },
+    
+    /**
+     * Method: read_cap_Get
+     */
+    read_cap_Get: function(obj, node) {
+        obj.get = node.getAttribute("onlineResource");
+    },
+    
+    /**
+     * Method: read_cap_Post
+     */
+    read_cap_Post: function(obj, node) {
+        obj.post = node.getAttribute("onlineResource");
+    },
+    
     CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_0_0" 
 
 });
\ No newline at end of file

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WFSCapabilities/v1.js
  */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSCapabilities.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/XML.js
  */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSDescribeFeatureType.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSDescribeFeatureType.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFSDescribeFeatureType.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/XML.js
  *

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -105,13 +106,31 @@
     },
 
     /**
-     * Method: read
+     * APIMethod: read
      * Parse the response from a transaction.  Because WFS is split into
      *     Transaction requests (create, update, and delete) and GetFeature
      *     requests (read), this method handles parsing of both types of
      *     responses.
+     *
+     * Parameters:
+     * data - {String | Document} The WFST document to read
+     * options - {Object} Options for the reader
+     *
+     * Valid options properties:
+     * output - {String} either "features" or "object". The default is
+     *     "features", which means that the method will return an array of
+     *     features. If set to "object", an object with a "features" property
+     *     and other properties read by the parser will be returned.
+     *
+     * Returns:
+     * {Array | Object} Output depending on the output option.
      */
-    read: function(data) {
+    read: function(data, options) {
+        options = options || {};
+        OpenLayers.Util.applyDefaults(options, {
+            output: "features"
+        });
+        
         if(typeof data == "string") { 
             data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
         }
@@ -119,8 +138,10 @@
             data = data.documentElement;
         }
         var obj = {};
-        this.readNode(data, obj);
-        if(obj.features) {
+        if(data) {
+            this.readNode(data, obj);
+        }
+        if(obj.features && options.output === "features") {
             obj = obj.features;
         }
         return obj;
@@ -179,36 +200,19 @@
                     attributes: {
                         service: "WFS",
                         version: this.version,
+                        outputFormat: options && options.outputFormat,
                         maxFeatures: options && options.maxFeatures,
                         "xsi:schemaLocation": this.schemaLocationAttr(options)
                     }
                 });
-                this.writeNode("Query", options, node);
-                return node;
-            },
-            "Query": function(options) {
-                options = OpenLayers.Util.extend({
-                    featureNS: this.featureNS,
-                    featurePrefix: this.featurePrefix,
-                    featureType: this.featureType,
-                    srsName: this.srsName
-                }, options);
-                // TODO: this is still version specific and should be separated out
-                // v1.0.0 does not allow srsName on wfs:Query
-                var node = this.createElementNSPlus("wfs:Query", {
-                    attributes: {
-                        typeName: (options.featureNS ? options.featurePrefix + ":" : "") +
-                            options.featureType,
-                        srsName: options.srsName
-                    }
-                });
-                if(options.featureNS) {
-                    node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS);
+                if (typeof this.featureType == "string") {
+                    this.writeNode("Query", options, node);
+                } else {
+                    for (var i=0,len = this.featureType.length; i<len; i++) { 
+                        options.featureType = this.featureType[i]; 
+                        this.writeNode("Query", options, node); 
+                    } 
                 }
-                if(options.filter) {
-                    this.setFilterProperty(options.filter);
-                    this.writeNode("ogc:Filter", options.filter, node);
-                }
                 return node;
             },
             "Transaction": function(features) {
@@ -248,15 +252,19 @@
                 }
                 
                 // add in geometry
-                this.writeNode(
-                    "Property", {name: this.geometryName, value: feature}, node
-                );
+                if (this.geometryName !== null) {
+                    this.writeNode(
+                        "Property", {name: this.geometryName, value: feature}, node
+                    );
+                }
         
                 // add in attributes
                 for(var key in feature.attributes) {
-                    this.writeNode(
-                        "Property", {name: key, value: feature.attributes[key]}, node
-                    );
+                    if(feature.attributes[key] !== undefined) {
+                        this.writeNode(
+                            "Property", {name: key, value: feature.attributes[key]}, node
+                        );
+                    }
                 }
                 
                 // add feature id filter
@@ -269,7 +277,9 @@
             "Property": function(obj) {
                 var node = this.createElementNSPlus("wfs:Property");
                 this.writeNode("Name", obj.name, node);
-                this.writeNode("Value", obj.value, node);
+                if(obj.value !== null) {
+                    this.writeNode("Value", obj.value, node);
+                }
                 return node;
             },
             "Name": function(name) {

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WFST/v1.js
  * @requires OpenLayers/Format/Filter/v1_0_0.js
@@ -20,6 +25,14 @@
      * {String} WFS version number.
      */
     version: "1.0.0",
+
+    /**
+     * APIProperty: srsNameInQuery
+     * {Boolean} If true the reference system is passed in Query requests
+     *     via the "srsName" attribute to the "wfs:Query" element, this
+     *     property defaults to false as it isn't WFS 1.0.0 compliant.
+     */
+    srsNameInQuery: false,
     
     /**
      * Property: schemaLocations
@@ -97,7 +110,8 @@
                     featureNS: this.featureNS,
                     featurePrefix: this.featurePrefix,
                     featureType: this.featureType,
-                    srsName: this.srsName
+                    srsName: this.srsName,
+                    srsNameInQuery: this.srsNameInQuery
                 }, options);
                 var node = this.createElementNSPlus("wfs:Query", {
                     attributes: {
@@ -105,6 +119,9 @@
                             options.featureType
                     }
                 });
+                if(options.srsNameInQuery && options.srsName) {
+                    node.setAttribute("srsName", options.srsName);
+                }
                 if(options.featureNS) {
                     node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS);
                 }

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_1_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WFST/v1.js
  * @requires OpenLayers/Format/Filter/v1_1_0.js
@@ -33,6 +38,12 @@
      * Constructor: OpenLayers.Format.WFST.v1_1_0
      * A class for parsing and generating WFS v1.1.0 transactions.
      *
+     * To read additional information like hit count (numberOfFeatures) from
+     * the  FeatureCollection, call the <OpenLayers.Format.WFST.v1.read> method
+     * with {output: "object"} as 2nd argument. Note that it is possible to
+     * just request the hit count from a WFS 1.1.0 server with the
+     * resultType="hits" request parameter.
+     *
      * Parameters:
      * options - {Object} Optional object whose properties will be set on the
      *     instance.
@@ -59,6 +70,12 @@
      */
     readers: {
         "wfs": OpenLayers.Util.applyDefaults({
+            "FeatureCollection": function(node, obj) {
+                obj.numberOfFeatures = parseInt(node.getAttribute(
+                    "numberOfFeatures"));
+                OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(
+                    this, arguments);
+            },
             "TransactionResponse": function(node, obj) {
                 obj.insertIds = [];
                 obj.success = false;
@@ -90,6 +107,13 @@
      */
     writers: {
         "wfs": OpenLayers.Util.applyDefaults({
+            "GetFeature": function(options) {
+                var node = OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this, arguments);
+                options && options.resultType && this.setAttributes(node, {
+                    resultType: options.resultType
+                });
+                return node;
+            },
             "Query": function(options) {
                 options = OpenLayers.Util.extend({
                     featureNS: this.featureNS,

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WFST.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WKT.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WKT.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WKT.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -151,7 +152,9 @@
         'multipoint': function(multipoint) {
             var array = [];
             for(var i=0, len=multipoint.components.length; i<len; ++i) {
-                array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+                array.push('(' +
+                           this.extract.point.apply(this, [multipoint.components[i]]) +
+                           ')');
             }
             return array.join(',');
         },
@@ -244,10 +247,12 @@
          * @private
          */
         'multipoint': function(str) {
-            var points = OpenLayers.String.trim(str).split(',');
+            var point;
+            var points = OpenLayers.String.trim(str).split(this.regExes.parenComma);
             var components = [];
             for(var i=0, len=points.length; i<len; ++i) {
-                components.push(this.parse.point.apply(this, [points[i]]).geometry);
+                point = points[i].replace(this.regExes.trimParens, '$1');
+                components.push(this.parse.point.apply(this, [point]).geometry);
             }
             return new OpenLayers.Feature.Vector(
                 new OpenLayers.Geometry.MultiPoint(components)

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -157,7 +158,8 @@
      * Method: read_wmc_LayerList
      */
     read_wmc_LayerList: function(context, node) {
-        context.layers = [];
+        // layersContext is an array containing info for each layer
+        context.layersContext = [];
         this.runChildNodes(context, node);
     },
     
@@ -165,50 +167,19 @@
      * Method: read_wmc_Layer
      */
     read_wmc_Layer: function(context, node) {
-        var layerInfo = {
-            params: this.layerParams || {},
-            options: {
-                visibility: (node.getAttribute("hidden") != "1"),
-                queryable: (node.getAttribute("queryable") == "1")
-                
-            },
+        var layerContext = {
+            visibility: (node.getAttribute("hidden") != "1"),
+            queryable: (node.getAttribute("queryable") == "1"),
             formats: [],
             styles: []
         };
-        this.runChildNodes(layerInfo, node);
+
+        this.runChildNodes(layerContext, node);
         // set properties common to multiple objects on layer options/params
-        layerInfo.params.layers = layerInfo.name;
-        layerInfo.options.maxExtent = layerInfo.maxExtent;
-        // create the layer
-        var layer = this.getLayerFromInfo(layerInfo);
-        context.layers.push(layer);
+        context.layersContext.push(layerContext);
     },
     
     /**
-     * Method: getLayerFromInfo
-     * Create a WMS layer from a layerInfo object.
-     *
-     * Parameters:
-     * layerInfo - {Object} An object representing a WMS layer.
-     *
-     * Returns:
-     * {<OpenLayers.Layer.WMS>} A WMS layer.
-     */
-    getLayerFromInfo: function(layerInfo) {
-        var options = layerInfo.options;
-        if (this.layerOptions) {
-            OpenLayers.Util.applyDefaults(options, this.layerOptions);
-        }
-        var layer = new OpenLayers.Layer.WMS(
-            layerInfo.title,
-            layerInfo.href,
-            layerInfo.params,
-            options
-        );
-        return layer;
-    },
-    
-    /**
      * Method: read_wmc_Extension
      */
     read_wmc_Extension: function(obj, node) {
@@ -218,8 +189,8 @@
     /**
      * Method: read_ol_units
      */
-    read_ol_units: function(layerInfo, node) {
-        layerInfo.options.units = this.getChildValue(node);
+    read_ol_units: function(layerContext, node) {
+        layerContext.units = this.getChildValue(node);
     },
     
     /**
@@ -236,100 +207,103 @@
     /**
      * Method: read_ol_transparent
      */
-    read_ol_transparent: function(layerInfo, node) {
-        layerInfo.params.transparent = this.getChildValue(node);
+    read_ol_transparent: function(layerContext, node) {
+        layerContext.transparent = this.getChildValue(node);
     },
 
     /**
      * Method: read_ol_numZoomLevels
      */
-    read_ol_numZoomLevels: function(layerInfo, node) {
-        layerInfo.options.numZoomLevels = parseInt(this.getChildValue(node));
+    read_ol_numZoomLevels: function(layerContext, node) {
+        layerContext.numZoomLevels = parseInt(this.getChildValue(node));
     },
 
     /**
      * Method: read_ol_opacity
      */
-    read_ol_opacity: function(layerInfo, node) {
-        layerInfo.options.opacity = parseFloat(this.getChildValue(node));
+    read_ol_opacity: function(layerContext, node) {
+        layerContext.opacity = parseFloat(this.getChildValue(node));
     },
 
     /**
      * Method: read_ol_singleTile
      */
-    read_ol_singleTile: function(layerInfo, node) {
-        layerInfo.options.singleTile = (this.getChildValue(node) == "true");
+    read_ol_singleTile: function(layerContext, node) {
+        layerContext.singleTile = (this.getChildValue(node) == "true");
     },
 
     /**
+     * Method: read_ol_tileSize
+     */
+    read_ol_tileSize: function(layerContext, node) {
+        var obj = {"width": node.getAttribute("width"), "height": node.getAttribute("height")};
+        layerContext.tileSize = obj;
+    },
+    
+    /**
      * Method: read_ol_isBaseLayer
      */
-    read_ol_isBaseLayer: function(layerInfo, node) {
-        layerInfo.options.isBaseLayer = (this.getChildValue(node) == "true");
+    read_ol_isBaseLayer: function(layerContext, node) {
+        layerContext.isBaseLayer = (this.getChildValue(node) == "true");
     },
 
     /**
      * Method: read_ol_displayInLayerSwitcher
      */
-    read_ol_displayInLayerSwitcher: function(layerInfo, node) {
-        layerInfo.options.displayInLayerSwitcher =
-            (this.getChildValue(node) == "true");
+    read_ol_displayInLayerSwitcher: function(layerContext, node) {
+        layerContext.displayInLayerSwitcher = (this.getChildValue(node) == "true");
     },
 
     /**
      * Method: read_wmc_Server
      */
-    read_wmc_Server: function(layerInfo, node) {
-        layerInfo.params.version = node.getAttribute("version");
-        this.runChildNodes(layerInfo, node);
+    read_wmc_Server: function(layerContext, node) {
+        layerContext.version = node.getAttribute("version");
+        var server = {};
+        var links = node.getElementsByTagName("OnlineResource");
+        if(links.length > 0) {
+            this.read_wmc_OnlineResource(server, links[0]);
+        }
+        layerContext.url = server.href;
     },
 
     /**
      * Method: read_wmc_FormatList
      */
-    read_wmc_FormatList: function(layerInfo, node) {
-        this.runChildNodes(layerInfo, node);
+    read_wmc_FormatList: function(layerContext, node) {
+        this.runChildNodes(layerContext, node);
     },
 
     /**
      * Method: read_wmc_Format
      */
-    read_wmc_Format: function(layerInfo, node) {
-        var format = this.getChildValue(node);
-        layerInfo.formats.push(format);
+    read_wmc_Format: function(layerContext, node) {
+        var format = {
+            value: this.getChildValue(node)
+        };
         if(node.getAttribute("current") == "1") {
-            layerInfo.params.format = format;
+            format.current = true;
         }
+        layerContext.formats.push(format);
     },
     
     /**
      * Method: read_wmc_StyleList
      */
-    read_wmc_StyleList: function(layerInfo, node) {
-        this.runChildNodes(layerInfo, node);
+    read_wmc_StyleList: function(layerContext, node) {
+        this.runChildNodes(layerContext, node);
     },
 
     /**
      * Method: read_wmc_Style
      */
-    read_wmc_Style: function(layerInfo, node) {
+    read_wmc_Style: function(layerContext, node) {
         var style = {};
         this.runChildNodes(style, node);
         if(node.getAttribute("current") == "1") {
-            // three style types to consider
-            // 1) linked SLD
-            // 2) inline SLD
-            // 3) named style
-            // running child nodes always gets name, optionally gets href or body
-            if(style.href) {
-                layerInfo.params.sld = style.href;
-            } else if(style.body) {
-                layerInfo.params.sld_body = style.body;
-            } else {
-                layerInfo.params.styles = style.name;
-            }
+            style.current = true;
         }
-        layerInfo.styles.push(style);
+        layerContext.styles.push(style);
     },
     
     /**
@@ -380,13 +354,13 @@
     /**
      * Method: read_wmc_MetadataURL
      */
-    read_wmc_MetadataURL: function(layerInfo, node) {
+    read_wmc_MetadataURL: function(layerContext, node) {
         var metadataURL = {};
         var links = node.getElementsByTagName("OnlineResource");
         if(links.length > 0) {
             this.read_wmc_OnlineResource(metadataURL, links[0]);
         }
-        layerInfo.options.metadataURL = metadataURL.href;
+        layerContext.metadataURL = metadataURL.href;
 
     },
 
@@ -401,18 +375,6 @@
     },
     
     /**
-     * Method: read_wmc_LatLonBoundingBox
-     */
-    read_wmc_LatLonBoundingBox: function(layer, node) {
-        layer.llbbox = [
-            parseFloat(node.getAttribute("minx")),
-            parseFloat(node.getAttribute("miny")),
-            parseFloat(node.getAttribute("maxx")),
-            parseFloat(node.getAttribute("maxy"))
-        ];
-    },
-
-    /**
      * Method: read_wmc_LegendURL
      */
     read_wmc_LegendURL: function(style, node) {
@@ -539,10 +501,10 @@
         node.appendChild(this.createElementDefaultNS(
             "BoundingBox", null,
             {
-                minx: bounds.left.toPrecision(10),
-                miny: bounds.bottom.toPrecision(10),
-                maxx: bounds.right.toPrecision(10),
-                maxy: bounds.top.toPrecision(10),
+                minx: bounds.left.toPrecision(18),
+                miny: bounds.bottom.toPrecision(18),
+                maxx: bounds.right.toPrecision(18),
+                maxy: bounds.top.toPrecision(18),
                 SRS: context.projection
             }
         ));
@@ -570,10 +532,10 @@
                 this.namespaces.ol, "ol:maxExtent"
             );
             this.setAttributes(maxExtent, {
-                minx: bounds.left.toPrecision(10),
-                miny: bounds.bottom.toPrecision(10),
-                maxx: bounds.right.toPrecision(10),
-                maxy: bounds.top.toPrecision(10)
+                minx: bounds.left.toPrecision(18),
+                miny: bounds.bottom.toPrecision(18),
+                maxx: bounds.right.toPrecision(18),
+                maxy: bounds.top.toPrecision(18)
             });
             node.appendChild(maxExtent);
         }
@@ -594,12 +556,8 @@
     write_wmc_LayerList: function(context) {
         var list = this.createElementDefaultNS("LayerList");
         
-        var layer;
-        for(var i=0, len=context.layers.length; i<len; ++i) {
-            layer = context.layers[i];
-            if(layer instanceof OpenLayers.Layer.WMS) {
-                list.appendChild(this.write_wmc_Layer(layer));
-            }
+        for(var i=0, len=context.layersContext.length; i<len; ++i) {
+            list.appendChild(this.write_wmc_Layer(context.layersContext[i]));
         }
         
         return list;
@@ -607,49 +565,40 @@
 
     /**
      * Method: write_wmc_Layer
-     * Create a Layer node given a layer object.
+     * Create a Layer node given a layer context object.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * context - {Object} A layer context object.}
      *
      * Returns:
      * {Element} A WMC Layer element node.
      */
-    write_wmc_Layer: function(layer) {
+    write_wmc_Layer: function(context) {
         var node = this.createElementDefaultNS(
             "Layer", null, {
-                queryable: layer.queryable ? "1" : "0",
-                hidden: layer.visibility ? "0" : "1"
+                queryable: context.queryable ? "1" : "0",
+                hidden: context.visibility ? "0" : "1"
             }
         );
         
         // required Server element
-        node.appendChild(this.write_wmc_Server(layer));
+        node.appendChild(this.write_wmc_Server(context));
 
         // required Name element
         node.appendChild(this.createElementDefaultNS(
-            "Name", layer.params["LAYERS"]
+            "Name", context.name
         ));
         
         // required Title element
         node.appendChild(this.createElementDefaultNS(
-            "Title", layer.name
+            "Title", context.title
         ));
 
         // optional MetadataURL element
-        if (layer.metadataURL) {
-            node.appendChild(this.write_wmc_MetadataURL(layer));
+        if (context.metadataURL) {
+            node.appendChild(this.write_wmc_MetadataURL(context.metadataURL));
         }
         
-        // optional FormatList element
-        node.appendChild(this.write_wmc_FormatList(layer));
-
-        // optional StyleList element
-        node.appendChild(this.write_wmc_StyleList(layer));
-        
-        // OpenLayers specific properties go in an Extension element
-        node.appendChild(this.write_wmc_LayerExtension(layer));
-
         return node;
     },
     
@@ -658,42 +607,41 @@
      * Add OpenLayers specific layer parameters to an Extension element.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} A WMS layer.
+     * context - {Object} A layer context object.
      *
      * Returns:
      * {Element} A WMC Extension element (for a layer).
      */
-    write_wmc_LayerExtension: function(layer) {
+    write_wmc_LayerExtension: function(context) {
         var node = this.createElementDefaultNS("Extension");
         
-        var bounds = layer.maxExtent;
+        var bounds = context.maxExtent;
         var maxExtent = this.createElementNS(
             this.namespaces.ol, "ol:maxExtent"
         );
         this.setAttributes(maxExtent, {
-            minx: bounds.left.toPrecision(10),
-            miny: bounds.bottom.toPrecision(10),
-            maxx: bounds.right.toPrecision(10),
-            maxy: bounds.top.toPrecision(10)
+            minx: bounds.left.toPrecision(18),
+            miny: bounds.bottom.toPrecision(18),
+            maxx: bounds.right.toPrecision(18),
+            maxy: bounds.top.toPrecision(18)
         });
         node.appendChild(maxExtent);
         
-        var param = layer.params["TRANSPARENT"];
-        if(param) {
-            var trans = this.createElementNS(
-                this.namespaces.ol, "ol:transparent"
+        if (context.tileSize && !context.singleTile) {
+            var size = this.createElementNS(
+                this.namespaces.ol, "ol:tileSize"
             );
-            trans.appendChild(this.createTextNode(param));
-            node.appendChild(trans);
+            this.setAttributes(size, context.tileSize);
+            node.appendChild(size);
         }
         
         var properties = [
-            "numZoomLevels", "units", "isBaseLayer",
+            "transparent", "numZoomLevels", "units", "isBaseLayer",
             "opacity", "displayInLayerSwitcher", "singleTile"
         ];
         var child;
         for(var i=0, len=properties.length; i<len; ++i) {
-            child = this.createOLPropertyNode(layer, properties[i]);
+            child = this.createOLPropertyNode(context, properties[i]);
             if(child) {
                 node.appendChild(child);
             }
@@ -725,116 +673,143 @@
 
     /**
      * Method: write_wmc_Server
-     * Create a Server node given a layer object.
+     * Create a Server node given a layer context object.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * context - {Object} Layer context object.
      *
      * Returns:
      * {Element} A WMC Server element node.
      */
-    write_wmc_Server: function(layer) {
+    write_wmc_Server: function(context) {
         var node = this.createElementDefaultNS("Server");
         this.setAttributes(node, {
             service: "OGC:WMS",
-            version: layer.params["VERSION"]
+            version: context.version
         });
         
         // required OnlineResource element
-        node.appendChild(this.write_wmc_OnlineResource(layer.url));
+        node.appendChild(this.write_wmc_OnlineResource(context.url));
         
         return node;
     },
 
     /**
      * Method: write_wmc_MetadataURL
-     * Create a MetadataURL node given a layer object.
+     * Create a MetadataURL node given a metadataURL string.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * metadataURL - {String} MetadataURL string value.
      *
      * Returns:
      * {Element} A WMC metadataURL element node.
      */
-    write_wmc_MetadataURL: function(layer) {
+    write_wmc_MetadataURL: function(metadataURL) {
         var node = this.createElementDefaultNS("MetadataURL");
 
         // required OnlineResource element
-        node.appendChild(this.write_wmc_OnlineResource(layer.metadataURL));
+        node.appendChild(this.write_wmc_OnlineResource(metadataURL));
 
         return node;
     },
 
     /**
      * Method: write_wmc_FormatList
-     * Create a FormatList node given a layer.
+     * Create a FormatList node given a layer context.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * context - {Object} Layer context object.
      *
      * Returns:
      * {Element} A WMC FormatList element node.
      */
-    write_wmc_FormatList: function(layer) {
+    write_wmc_FormatList: function(context) {
         var node = this.createElementDefaultNS("FormatList");
-        node.appendChild(this.createElementDefaultNS(
-            "Format", layer.params["FORMAT"], {current: "1"}
-        ));
+        for (var i=0, len=context.formats.length; i<len; i++) {
+            var format = context.formats[i];
+            node.appendChild(this.createElementDefaultNS(
+                "Format",
+                format.value,
+                (format.current && format.current == true) ?
+                    {current: "1"} : null
+            ));
+        }
 
         return node;
     },
 
     /**
      * Method: write_wmc_StyleList
-     * Create a StyleList node given a layer.
+     * Create a StyleList node given a layer context.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * context - {Object} Layer context object.
      *
      * Returns:
      * {Element} A WMC StyleList element node.
      */
     write_wmc_StyleList: function(layer) {
         var node = this.createElementDefaultNS("StyleList");
-        var style = this.createElementDefaultNS(
-            "Style", null, {current: "1"}
-        );
-        
-        // Style can come from one of three places (prioritized as below):
-        // 1) an SLD parameter
-        // 2) and SLD_BODY parameter
-        // 3) the STYLES parameter
-        
-        if(layer.params["SLD"]) {
-            // create link from SLD parameter
-            var sld = this.createElementDefaultNS("SLD");
-            var link = this.write_wmc_OnlineResource(layer.params["SLD"]);
-            sld.appendChild(link);
-            style.appendChild(sld);
-        } else if(layer.params["SLD_BODY"]) {
-            // include sld fragment from SLD_BODY parameter
-            var sld = this.createElementDefaultNS("SLD");
-            var body = layer.params["SLD_BODY"];
-            // read in body as xml doc - assume proper namespace declarations
-            var doc = OpenLayers.Format.XML.prototype.read.apply(this, [body]);
-            // append to StyledLayerDescriptor node
-            var imported = doc.documentElement;
-            if(sld.ownerDocument && sld.ownerDocument.importNode) {
-                imported = sld.ownerDocument.importNode(imported, true);
+
+        var styles = layer.styles;
+        if (styles && styles instanceof Array) {
+            var sld;
+            for (var i=0, len=styles.length; i<len; i++) {
+                var s = styles[i];
+                // three style types to consider
+                // [1] linked SLD
+                // [2] inline SLD
+                // [3] named style
+                // running child nodes always gets name, optionally gets href or body
+                var style = this.createElementDefaultNS(
+                    "Style",
+                    null,
+                    (s.current && s.current == true) ?
+                    {current: "1"} : null
+                );
+                if(s.href) { // [1]
+                    sld = this.createElementDefaultNS("SLD");
+                    var link = this.write_wmc_OnlineResource(s.href);
+                    sld.appendChild(link);
+                    // Name is required.
+                    sld.appendChild(this.createElementDefaultNS("Name", s.name));
+                    // Title is optional.
+                    if (s.title) {
+                        sld.appendChild(this.createElementDefaultNS("Title", s.title));
+                    }
+                    style.appendChild(sld);
+                } else if(s.body) { // [2]
+                    sld = this.createElementDefaultNS("SLD");
+                    // read in body as xml doc - assume proper namespace declarations
+                    var doc = OpenLayers.Format.XML.prototype.read.apply(this, [s.body]);
+                    // append to StyledLayerDescriptor node
+                    var imported = doc.documentElement;
+                    if(sld.ownerDocument && sld.ownerDocument.importNode) {
+                        imported = sld.ownerDocument.importNode(imported, true);
+                    }
+                    sld.appendChild(imported);
+                    // Name is required.
+                    sld.appendChild(this.createElementDefaultNS("Name", s.name));
+                    // Title is optional.
+                    if (s.title) {
+                        sld.appendChild(this.createElementDefaultNS("Title", s.title));
+                    }
+                    style.appendChild(sld);            
+                } else { // [3]
+                    // both Name and Title are required.
+                    style.appendChild(this.createElementDefaultNS("Name", s.name));
+                    style.appendChild(this.createElementDefaultNS("Title", s.title));
+                    // Abstract is optional
+                    if (s['abstract']) { // abstract is a js keyword
+                        style.appendChild(this.createElementDefaultNS(
+                            "Abstract", s['abstract']
+                        ));
+                    }
+                }
+                node.appendChild(style);
             }
-            sld.appendChild(imported);
-            style.appendChild(sld);            
-        } else {
-            // use name(s) from STYLES parameter
-            var name = layer.params["STYLES"] ?
-                layer.params["STYLES"] : this.defaultStyleName;
-            
-            style.appendChild(this.createElementDefaultNS("Name", name));
-            style.appendChild(this.createElementDefaultNS(
-                "Title", this.defaultStyleTitle
-            ));
         }
-        node.appendChild(style);
+
         return node;
     },
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -44,6 +45,32 @@
         );
     },
 
+    /**
+     * Method: write_wmc_Layer
+     * Create a Layer node given a layer context object. This method adds
+     *     elements specific to version 1.0.0.
+     *
+     * Parameters:
+     * context - {Object} A layer context object.}
+     *
+     * Returns:
+     * {Element} A WMC Layer element node.
+     */
+    write_wmc_Layer: function(context) {
+        var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
+            this, [context]
+        );
+    
+        // optional FormatList element
+        node.appendChild(this.write_wmc_FormatList(context));
+
+        // optional StyleList element
+        node.appendChild(this.write_wmc_StyleList(context));
+        
+        // OpenLayers specific properties go in an Extension element
+        node.appendChild(this.write_wmc_LayerExtension(context));
+    },    
+
     CLASS_NAME: "OpenLayers.Format.WMC.v1_0_0" 
 
-});
\ No newline at end of file
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_1_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -53,11 +54,14 @@
      * Read a sld:MinScaleDenominator node.
      *
      * Parameters:
-     * layerInfo - {Object} An object representing a layer.
+     * layerContext - {Object} An object representing a layer.
      * node - {Element} An element node.
      */
-    read_sld_MinScaleDenominator: function(layerInfo, node) {
-        layerInfo.options.maxScale = this.getChildValue(node);
+    read_sld_MinScaleDenominator: function(layerContext, node) {
+        var minScaleDenominator = parseFloat(this.getChildValue(node));
+        if (minScaleDenominator > 0) {
+            layerContext.maxScale = minScaleDenominator;
+        }
     },
 
     /**
@@ -65,52 +69,59 @@
      * Read a sld:MaxScaleDenominator node.
      *
      * Parameters:
-     * layerInfo - {Object} An object representing a layer.
+     * layerContext - {Object} An object representing a layer.
      * node - {Element} An element node.
      */
-    read_sld_MaxScaleDenominator: function(layerInfo, node) {
-        layerInfo.options.minScale = this.getChildValue(node);
+    read_sld_MaxScaleDenominator: function(layerContext, node) {
+        layerContext.minScale = parseFloat(this.getChildValue(node));
     },
 
     /**
      * Method: write_wmc_Layer
-     * Create a Layer node given a layer object.  This method adds elements
-     *     specific to version 1.1.0.
+     * Create a Layer node given a layer context object. This method adds
+     *     elements specific to version 1.1.0.
      *
      * Parameters:
-     * layer - {<OpenLayers.Layer.WMS>} Layer object.
+     * context - {Object} A layer context object.}
      *
      * Returns:
      * {Element} A WMC Layer element node.
      */
-    write_wmc_Layer: function(layer) {
+    write_wmc_Layer: function(context) {
         var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
-            this, [layer]
+            this, [context]
         );
         
         // min/max scale denominator elements go before the 4th element in v1
-        if(layer.options.resolutions || layer.options.scales ||
-           layer.options.minResolution || layer.options.maxScale) {
+        if(context.maxScale) {
             var minSD = this.createElementNS(
                 this.namespaces.sld, "sld:MinScaleDenominator"
             );
-            minSD.appendChild(this.createTextNode(layer.maxScale.toPrecision(10)));
-            node.insertBefore(minSD, node.childNodes[3]);
+            minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));
+            node.appendChild(minSD);
         }
         
-        if(layer.options.resolutions || layer.options.scales ||
-           layer.options.maxResolution || layer.options.minScale) {
+        if(context.minScale) {
             var maxSD = this.createElementNS(
                 this.namespaces.sld, "sld:MaxScaleDenominator"
             );
-            maxSD.appendChild(this.createTextNode(layer.minScale.toPrecision(10)));
-            node.insertBefore(maxSD, node.childNodes[4]);
+            maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));
+            node.appendChild(maxSD);
         }
+
+        // optional FormatList element
+        node.appendChild(this.write_wmc_FormatList(context));
+
+        // optional StyleList element
+        node.appendChild(this.write_wmc_StyleList(context));
         
+        // OpenLayers specific properties go in an Extension element
+        node.appendChild(this.write_wmc_LayerExtension(context));
+        
         return node;
         
     },
 
     CLASS_NAME: "OpenLayers.Format.WMC.v1_1_0" 
 
-});
\ No newline at end of file
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMC.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,9 +1,11 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Format/XML.js
+ * @requires OpenLayers/Format/Context.js
  */
 
 /**
@@ -13,7 +15,7 @@
  * Inherits from:
  *  - <OpenLayers.Format.XML>
  */
-OpenLayers.Format.WMC = OpenLayers.Class({
+OpenLayers.Format.WMC = OpenLayers.Class(OpenLayers.Format.Context, {
     
     /**
      * APIProperty: defaultVersion
@@ -22,190 +24,126 @@
     defaultVersion: "1.1.0",
     
     /**
-     * APIProperty: version
-     * {String} Specify a version string if one is known.
-     */
-    version: null,
-
-    /**
-     * Property: layerOptions
-     * {Object} Default options for layers created by the parser. These
-     *     options are overridden by the options which are read from the 
-     *     capabilities document.
-     */
-    layerOptions: null, 
-
-    /**
-     * Property: layerParams
-     * {Object} Default parameters for layers created by the parser. This
-     *     can be used to override DEFAULT_PARAMS for OpenLayers.Layer.WMS.
-     */
-    layerParams: null,
-    
-    /**
-     * Property: parser
-     * {Object} Instance of the versioned parser.  Cached for multiple read and
-     *     write calls of the same version.
-     */
-    parser: null,
-
-    /**
-     * Constructor: OpenLayers.Format.WMC
-     * Create a new parser for WMC docs.
+     * Method: getParser
+     * Get the WMC parser given a version. Create a new parser if it does not
+     * already exist.
      *
      * Parameters:
-     * options - {Object} An optional object whose properties will be set on
-     *     this instance.
-     */
-    initialize: function(options) {
-        OpenLayers.Util.extend(this, options);
-        this.options = options;
-    },
-
-    /**
-     * APIMethod: read
-     * Read WMC data from a string, and return an object with map properties
-     *     and a list of layers. 
-     * 
-     * Parameters: 
-     * data - {String} or {DOMElement} data to read/parse.
-     * options - {Object} The options object must contain a map property.  If
-     *     the map property is a string, it must be the id of a dom element
-     *     where the new map will be placed.  If the map property is an
-     *     <OpenLayers.Map>, the layers from the context document will be added
-     *     to the map.
+     * version - {String} The version of the parser.
      *
      * Returns:
-     * {<OpenLayers.Map>} A map based on the context.
+     * {<OpenLayers.Format.WMC.v1>} A WMC parser.
      */
-    read: function(data, options) {
-        if(typeof data == "string") {
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        var root = data.documentElement;
-        var version = this.version;
-        if(!version) {
-            version = root.getAttribute("version");
-            if(!version) {
-                version = this.defaultVersion;
-            }
-        }
-        if(!this.parser || this.parser.VERSION != version) {
+    getParser: function(version) {
+        var v = version || this.version || this.defaultVersion;
+        if(!this.parser || this.parser.VERSION != v) {
             var format = OpenLayers.Format.WMC[
-                "v" + version.replace(/\./g, "_")
+                "v" + v.replace(/\./g, "_")
             ];
             if(!format) {
-                throw "Can't find a WMC parser for version " +
-                      version;
+                throw "Can't find a WMC parser for version " + v;
             }
             this.parser = new format(this.options);
         }
-        var context = this.parser.read(data, options);
-        var map;
-        if(options.map) {
-            this.context = context;
-            if(options.map instanceof OpenLayers.Map) {
-                map = this.mergeContextToMap(context, options.map);
-            } else {
-                map = this.contextToMap(context, options.map);
-            }
-        } else {
-            // not documented as part of the API, provided as a non-API option
-            map = context;
-        }
-        return map;
+        return this.parser;
     },
-    
+
     /**
-     * Method: contextToMap
-     * Create a map given a context object.
+     * Method: layerToContext
+     * Create a layer context object given a wms layer object.
      *
      * Parameters:
-     * context - {Object} The context object.
-     * id - {String | Element} The dom element or element id that will contain
-     *     the map.
+     * obj - {<OpenLayers.Layer.WMS>} The layer.
      *
      * Returns:
-     * {<OpenLayers.Map>} A map based on the context object.
+     * {Object} A layer context object.
      */
-    contextToMap: function(context, id) {
-        var map = new OpenLayers.Map(id, {
-            maxExtent: context.maxExtent,
-            projection: context.projection
-        });
-        map.addLayers(context.layers);
-        map.setCenter(
-            context.bounds.getCenterLonLat(),
-            map.getZoomForExtent(context.bounds, true)
-        );
-        return map;
+    layerToContext: function(layer) {
+        var parser = this.getParser();
+        var layerContext = {
+            queryable: layer.queryable,
+            visibility: layer.visibility,
+            name: layer.params["LAYERS"],
+            title: layer.name,
+            metadataURL: layer.metadataURL,
+            version: layer.params["VERSION"],
+            url: layer.url,
+            maxExtent: layer.maxExtent,
+            transparent: layer.params["TRANSPARENT"],
+            numZoomLevels: layer.numZoomLevels,
+            units: layer.units,
+            isBaseLayer: layer.isBaseLayer,
+            opacity: layer.opacity,
+            displayInLayerSwitcher: layer.displayInLayerSwitcher,
+            singleTile: layer.singleTile,
+            tileSize: (layer.singleTile || !layer.tileSize) ? 
+                undefined : {width: layer.tileSize.w, height: layer.tileSize.h},
+            minScale : (layer.options.resolutions ||
+                        layer.options.scales || 
+                        layer.options.maxResolution || 
+                        layer.options.minScale) ? 
+                        layer.minScale : undefined,
+            maxScale : (layer.options.resolutions ||
+                        layer.options.scales || 
+                        layer.options.minResolution || 
+                        layer.options.maxScale) ? 
+                        layer.maxScale : undefined,
+            formats: [{
+                value: layer.params["FORMAT"],
+                current: true
+            }],
+            styles: [{
+                href: layer.params["SLD"],
+                body: layer.params["SLD_BODY"],
+                name: layer.params["STYLES"] || parser.defaultStyleName,
+                title: parser.defaultStyleTitle,
+                current: true
+            }]
+        };
+        return layerContext;
     },
     
     /**
-     * Method: mergeContextToMap
-     * Add layers from a context object to a map.
+     * Method: toContext
+     * Create a context object free from layer given a map or a
+     * context object.
      *
      * Parameters:
-     * context - {Object} The context object.
-     * map - {<OpenLayers.Map>} The map.
+     * obj - {<OpenLayers.Map> | Object} The map or context.
      *
      * Returns:
-     * {<OpenLayers.Map>} The same map with layers added.
+     * {Object} A context object.
      */
-    mergeContextToMap: function(context, map) {
-        map.addLayers(context.layers);
-        return map;
-    },
-
-    /**
-     * APIMethod: write
-     * Write a WMC document given a map.
-     *
-     * Parameters:
-     * obj - {<OpenLayers.Map> | Object} A map or context object.
-     * options - {Object} Optional configuration object.
-     *
-     * Returns:
-     * {String} A WMC document string.
-     */
-    write: function(obj, options) {
+    toContext: function(obj) {
+        var context = {};
+        var layers = obj.layers;
         if(obj.CLASS_NAME == "OpenLayers.Map") {
-            obj = this.mapToContext(obj);
+            context.bounds = obj.getExtent();
+            context.maxExtent = obj.maxExtent;
+            context.projection = obj.projection;
+            context.size = obj.getSize();
         }
-        var version = (options && options.version) ||
-                      this.version || this.defaultVersion;
-        if(!this.parser || this.parser.VERSION != version) {
-            var format = OpenLayers.Format.WMC[
-                "v" + version.replace(/\./g, "_")
-            ];
-            if(!format) {
-                throw "Can't find a WMS capabilities parser for version " +
-                      version;
+        else {
+            // copy all obj properties except the "layers" property
+            OpenLayers.Util.applyDefaults(context, obj);
+            if(context.layers != undefined) {
+                delete(context.layers);
             }
-            this.parser = new format(this.options);
         }
-        var wmc = this.parser.write(obj, options);
-        return wmc;
-    },
-    
-    /**
-     * Method: mapToContext
-     * Create a context object given a map.
-     *
-     * Parameters:
-     * map - {<OpenLayers.Map>} The map.
-     *
-     * Returns:
-     * {Object} A context object.
-     */
-    mapToContext: function(map) {
-        var context = {
-            bounds: map.getExtent(),
-            maxExtent: map.maxExtent,
-            projection: map.projection,
-            layers: map.layers,
-            size: map.getSize()
-        };
+
+        if (context.layersContext == undefined) {
+            context.layersContext = [];
+        }
+
+        // let's convert layers into layersContext object (if any)
+        if (layers != undefined && layers instanceof Array) {
+            for (var i=0, len=layers.length; i<len; i++) {
+                var layer = layers[i];
+                if(layer instanceof OpenLayers.Layer.WMS) {
+                    context.layersContext.push(this.layerToContext(layer));
+                }
+            }
+        }
         return context;
     },
 

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,418 @@
+/* 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/Format/WMSCapabilities.js
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities.v1
+ * Abstract class not to be instantiated directly. Creates
+ * the common parts for both WMS 1.1.X and WMS 1.3.X.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMSCapabilities.v1 = OpenLayers.Class(
+    OpenLayers.Format.XML, {
+    
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        wms: "http://www.opengis.net/wms",
+        xlink: "http://www.w3.org/1999/xlink",
+        xsi: "http://www.w3.org/2001/XMLSchema-instance"
+    },
+
+    /**
+     * Property: defaultPrefix
+     */
+    defaultPrefix: "wms",
+    
+    /**
+     * Constructor: OpenLayers.Format.WMSCapabilities.v1
+     * Create an instance of one of the subclasses.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return a list of layers. 
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Array} List of named layers.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+    
+        // postprocess the layer list
+        this.postProcessLayers(capabilities);
+    
+        return capabilities;
+    },
+
+    /**
+     * Method: postProcessLayers
+     * Post process the layers, so that the nested layer structure is converted
+     * to a flat layer list with only named layers.
+     *
+     * Parameters:
+     * capabilities - {Object} The object (structure) returned by the parser with
+     *     all the info from the GetCapabilities response.
+     */
+    postProcessLayers: function(capabilities) {
+        if (capabilities.capability) {
+            capabilities.capability.layers = [];
+            var layers = capabilities.capability.nestedLayers;
+            for (var i=0, len = layers.length; i<len; ++i) {
+                var layer = layers[i];
+                this.processLayer(capabilities.capability, layer);
+            }
+        }
+    },
+
+    /**
+     * Method: processLayer
+     * Recursive submethod of postProcessLayers. This function will among
+     * others deal with property inheritance.
+     *
+     * Parameters:
+     * capability - {Object} The capability part of the capabilities object
+     * layer - {Object} The layer that needs processing
+     * parentLayer - {Object} The parent layer of the respective layer
+    */
+    processLayer: function(capability, layer, parentLayer) {
+        if (layer.formats === undefined) {
+            layer.formats = capability.request.getmap.formats;
+        }
+
+        // deal with property inheritance
+        if(parentLayer) {
+            // add style
+            layer.styles = layer.styles.concat(parentLayer.styles);
+            var attributes = ["queryable",
+                              "cascaded",
+                              "fixedWidth",
+                              "fixedHeight",
+                              "opaque",
+                              "noSubsets",
+                              "llbbox",
+                              "minScale",
+                              "maxScale",
+                              "attribution"];
+
+            var complexAttr = ["srs",
+                               "bbox",
+                               "dimensions",
+                               "authorityURLs"];
+            
+            var key;
+            for (var j=0; j<attributes.length; j++) {
+                key = attributes[j];
+                if (key in parentLayer) {
+                    // only take parent value if not present (null or undefined)
+                    if (layer[key] == null) {
+                        layer[key] = parentLayer[key];
+                    }
+                    // if attribute isn't present, and we haven't
+                    // inherited anything from a parent layer
+                    // set to default value
+                    if (layer[key] == null) {
+                        var intAttr = ["cascaded", "fixedWidth", "fixedHeight"];
+                        var boolAttr = ["queryable", "opaque", "noSubsets"];
+                        if (OpenLayers.Util.indexOf(intAttr, key) != -1) {
+                            layer[key] = 0;
+                        }
+                        if (OpenLayers.Util.indexOf(boolAttr, key) != -1) {
+                            layer[key] = false;
+                        }
+                    }
+                }
+            }
+
+            for (var j=0; j<complexAttr.length; j++) {
+                key = complexAttr[j];
+                layer[key] = OpenLayers.Util.extend(
+                    layer[key], parentLayer[key]);
+            }
+        }
+
+        // process sublayers
+        for (var i=0, len=layer.nestedLayers.length; i<len; i++) {
+            var childLayer = layer.nestedLayers[i];
+            this.processLayer(capability, childLayer, layer);
+        }
+        
+        if (layer.name) {
+            capability.layers.push(layer);
+        }
+    
+    },
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": {
+            "Service": function(node, obj) {
+                obj.service = {};
+                this.readChildNodes(node, obj.service);
+            },
+            "Name": function(node, obj) {
+                obj.name = this.getChildValue(node);
+            },
+            "Title": function(node, obj) {
+                obj.title = this.getChildValue(node);
+            },
+            "Abstract": function(node, obj) {
+                obj["abstract"] = this.getChildValue(node);
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = {};
+                bbox.bbox = [
+                    parseFloat(node.getAttribute("minx")),
+                    parseFloat(node.getAttribute("miny")),
+                    parseFloat(node.getAttribute("maxx")),
+                    parseFloat(node.getAttribute("maxy"))
+                ];
+                var res = {
+                    x: parseFloat(node.getAttribute("resx")),
+                    y: parseFloat(node.getAttribute("resy"))
+                };
+
+                if (! (isNaN(res.x) && isNaN(res.y))) {
+                    bbox.res = res;
+                }
+                // return the bbox so that descendant classes can set the
+                // CRS and SRS and add it to the obj
+                return bbox;
+            },
+            "OnlineResource": function(node, obj) {
+                obj.href = this.getAttributeNS(node, this.namespaces.xlink, 
+                    "href");
+            },
+            "ContactInformation": function(node, obj) {
+                obj.contactInformation = {};
+                this.readChildNodes(node, obj.contactInformation);
+            },
+            "ContactPersonPrimary": function(node, obj) {
+                obj.personPrimary = {};
+                this.readChildNodes(node, obj.personPrimary);
+            },
+            "ContactPerson": function(node, obj) {
+                obj.person = this.getChildValue(node);
+            },
+            "ContactOrganization": function(node, obj) {
+                obj.organization = this.getChildValue(node);
+            },
+            "ContactPosition": function(node, obj) {
+                obj.position = this.getChildValue(node);
+            },
+            "ContactAddress": function(node, obj) {
+                obj.contactAddress = {};
+                this.readChildNodes(node, obj.contactAddress);
+            },
+            "AddressType": function(node, obj) {
+                obj.type = this.getChildValue(node);
+            },
+            "Address": function(node, obj) {
+                obj.address = this.getChildValue(node);
+            },
+            "City": function(node, obj) {
+                obj.city = this.getChildValue(node);
+            },
+            "StateOrProvince": function(node, obj) {
+                obj.stateOrProvince = this.getChildValue(node);
+            },
+            "PostCode": function(node, obj) {
+                obj.postcode = this.getChildValue(node);
+            },
+            "Country": function(node, obj) {
+                obj.country = this.getChildValue(node);
+            },
+            "ContactVoiceTelephone": function(node, obj) {
+                obj.phone = this.getChildValue(node);
+            },
+            "ContactFacsimileTelephone": function(node, obj) {
+                obj.fax = this.getChildValue(node);
+            },
+            "ContactElectronicMailAddress": function(node, obj) {
+                obj.email = this.getChildValue(node);
+            },
+            "Fees": function(node, obj) {
+                var fees = this.getChildValue(node);
+                if (fees && fees.toLowerCase() != "none") {
+                    obj.fees = fees;
+                }
+            },
+            "AccessConstraints": function(node, obj) {
+                var constraints = this.getChildValue(node);
+                if (constraints && constraints.toLowerCase() != "none") {
+                    obj.accessConstraints = constraints;
+                }
+            },
+            "Capability": function(node, obj) {
+                obj.capability = {nestedLayers: []};
+                this.readChildNodes(node, obj.capability);
+            },
+            "Request": function(node, obj) {
+                obj.request = {};
+                this.readChildNodes(node, obj.request);
+            },
+            "GetCapabilities": function(node, obj) {
+                obj.getcapabilities = {formats: []};
+                this.readChildNodes(node, obj.getcapabilities);
+            },
+            "Format": function(node, obj) {
+                if (obj.formats instanceof Array) {
+                    obj.formats.push(this.getChildValue(node));
+                } else {
+                    obj.format = this.getChildValue(node);
+                }
+            },
+            "DCPType": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "HTTP": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Get": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Post": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "GetMap": function(node, obj) {
+                obj.getmap = {formats: []};
+                this.readChildNodes(node, obj.getmap);
+            },
+            "GetFeatureInfo": function(node, obj) {
+                obj.getfeatureinfo = {formats: []};
+                this.readChildNodes(node, obj.getfeatureinfo);
+            },
+            "Exception": function(node, obj) {
+                obj.exception = {formats: []};
+                this.readChildNodes(node, obj.exception);
+            },
+            "Layer": function(node, obj) {
+                var attrNode = node.getAttributeNode("queryable");
+                var queryable = (attrNode && attrNode.specified) ? 
+                    node.getAttribute("queryable") : null;
+                attrNode = node.getAttributeNode("cascaded");
+                var cascaded = (attrNode && attrNode.specified) ?
+                    node.getAttribute("cascaded") : null;
+                attrNode = node.getAttributeNode("opaque");
+                var opaque = (attrNode && attrNode.specified) ?
+                    node.getAttribute('opaque') : null;
+                var noSubsets = node.getAttribute('noSubsets');
+                var fixedWidth = node.getAttribute('fixedWidth');
+                var fixedHeight = node.getAttribute('fixedHeight');
+                var layer = {nestedLayers: [], styles: [], srs: {}, 
+                    metadataURLs: [], bbox: {}, dimensions: {},
+                    authorityURLs: {}, identifiers: {}, keywords: [],
+                    queryable: (queryable && queryable !== "") ? 
+                        ( queryable === "1" || queryable === "true" ) : null,
+                    cascaded: (cascaded !== null) ? parseInt(cascaded) : null,
+                    opaque: opaque ? 
+                        (opaque === "1" || opaque === "true" ) : null,
+                    noSubsets: (noSubsets !== null) ? 
+                        ( noSubsets === "1" || noSubsets === "true" ) : null,
+                    fixedWidth: (fixedWidth != null) ? 
+                        parseInt(fixedWidth) : null,
+                    fixedHeight: (fixedHeight != null) ? 
+                        parseInt(fixedHeight) : null
+                };
+                obj.nestedLayers.push(layer);
+                this.readChildNodes(node, layer);
+                if(layer.name) {
+                    var parts = layer.name.split(":");
+                    if(parts.length > 0) {
+                        layer.prefix = parts[0];
+                    }
+                }
+            },
+            "Attribution": function(node, obj) {
+                obj.attribution = {};
+                this.readChildNodes(node, obj.attribution);
+            },
+            "LogoURL": function(node, obj) {
+                obj.logo = {
+                    width: node.getAttribute("width"),
+                    height: node.getAttribute("height")
+                };
+                this.readChildNodes(node, obj.logo);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                obj.styles.push(style);
+                this.readChildNodes(node, style);
+            },
+            "LegendURL": function(node, obj) {
+                var legend = {
+                    width: node.getAttribute("width"),
+                    height: node.getAttribute("height")
+                };
+                obj.legend = legend;
+                this.readChildNodes(node, legend);
+            },
+            "MetadataURL": function(node, obj) {
+                var metadataURL = {type: node.getAttribute("type")};
+                obj.metadataURLs.push(metadataURL);
+                this.readChildNodes(node, metadataURL);
+            },
+            "DataURL": function(node, obj) {
+                obj.dataURL = {};
+                this.readChildNodes(node, obj.dataURL);
+            },
+            "FeatureListURL": function(node, obj) {
+                obj.featureListURL = {};
+                this.readChildNodes(node, obj.featureListURL);
+            },
+            "AuthorityURL": function(node, obj) {
+                var name = node.getAttribute("name");
+                var authority = {};
+                this.readChildNodes(node, authority);
+                obj.authorityURLs[name] = authority.href;
+            },
+            "Identifier": function(node, obj) {
+                var authority = node.getAttribute("authority");
+                obj.identifiers[authority] = this.getChildValue(node);
+            },
+            "KeywordList": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "SRS": function(node, obj) {
+                obj.srs[this.getChildValue(node)] = true;
+            }
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1" 
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,10 @@
+/* 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/Format/WMSCapabilities.js
- * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/WMSCapabilities/v1.js
  */
 
 /**
@@ -8,259 +12,107 @@
  * Abstract class not to be instantiated directly.
  * 
  * Inherits from:
- *  - <OpenLayers.Format.XML>
+ *  - <OpenLayers.Format.WMSCapabilities.v1>
  */
 OpenLayers.Format.WMSCapabilities.v1_1 = OpenLayers.Class(
-    OpenLayers.Format.XML, {
+    OpenLayers.Format.WMSCapabilities.v1, {
     
     /**
-     * Constructor: OpenLayers.Format.WMSCapabilities.v1_1
-     * Create an instance of one of the subclasses.
-     *
-     * Parameters:
-     * options - {Object} An optional object whose properties will be set on
-     *     this instance.
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
      */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-        this.options = options;
-    },
-
-    /**
-     * APIMethod: read
-     * Read capabilities data from a string, and return a list of layers. 
-     * 
-     * Parameters: 
-     * data - {String} or {DOMElement} data to read/parse.
-     *
-     * Returns:
-     * {Array} List of named layers.
-     */
-    read: function(data) {
-        if(typeof data == "string") {
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        var capabilities = {};
-        var root = data.documentElement;
-        this.runChildNodes(capabilities, root);
-        return capabilities;
-    },
-    
-    /**
-     * Method: runChildNodes
-     */
-    runChildNodes: function(obj, node) {
-        var children = node.childNodes;
-        var childNode, processor;
-        for(var i=0; i<children.length; ++i) {
-            childNode = children[i];
-            if(childNode.nodeType == 1) {
-                processor = this["read_cap_" + childNode.nodeName];
-                if(processor) {
-                    processor.apply(this, [obj, childNode]);
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "WMT_MS_Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Keyword": function(node, obj) {
+                if (obj.keywords) {
+                    obj.keywords.push(this.getChildValue(node));
                 }
-            }
-        }
-    },
-    
-    /**
-     * Method: read_cap_Capability
-     */
-    read_cap_Capability: function(capabilities, node) {
-        var capability = {
-            layers: []
-        };
-        this.runChildNodes(capability, node);
-        capabilities.capability = capability;
-    },
-    
-    /**
-     * Method: read_cap_Request
-     */
-    read_cap_Request: function(obj, node) {
-        var request = {};
-        this.runChildNodes(request, node);
-        obj.request = request;
-    },
-    
-    /**
-     * Method: read_cap_GetMap
-     */
-    read_cap_GetMap: function(request, node) {
-        var getmap = {
-            formats: []
-        };
-        this.runChildNodes(getmap, node);
-        request.getmap = getmap;
-    },
-    
-    /**
-     * Method: read_cap_Format
-     */
-    read_cap_Format: function(obj, node) {
-        if(obj.formats) {
-            obj.formats.push(this.getChildValue(node));
-        }
-    },
-    
-    /**
-     * Method: read_cap_DCPType
-     * Super simplified HTTP href extractor.  Assumes the first online resource
-     *     will work.
-     */
-    read_cap_DCPType: function(obj, node) {
-        var children = node.getElementsByTagName("OnlineResource");
-        if(children.length > 0) {
-            this.read_cap_OnlineResource(obj, children[0]);
-        }
-    },
-
-    /**
-     * Method: read_cap_Service
-     */
-    read_cap_Service: function(capabilities, node) {
-        var service = {};
-        this.runChildNodes(service, node);
-        capabilities.service = service;
-    },
-
-    /**
-     * Method: read_cap_Layer
-     */
-    read_cap_Layer: function(capability, node, parentLayer) {
-        var layer = {
-            formats: capability.request.getmap.formats || [],
-            styles: [],
-            queryable: (node.getAttribute("queryable") === "1" 
-                        || node.getAttribute("queryable") === "true")
-        };
-        // deal with property inheritance
-        if(parentLayer) {
-            // add style
-            layer.styles = layer.styles.concat(parentLayer.styles);
-            // use llbbox
-            layer.llbbox = parentLayer.llbbox;
-            // use min/maxScale
-            layer.minScale = parentLayer.minScale;
-            layer.maxScale = parentLayer.maxScale;
-        }
-        var children = node.childNodes;
-        var childNode, nodeName, processor;
-        for(var i=0; i<children.length; ++i) {
-            childNode = children[i];
-            nodeName = childNode.nodeName;
-            processor = this["read_cap_" + childNode.nodeName];
-            if(processor) {
-                if(nodeName == "Layer") {
-                    processor.apply(this, [capability, childNode, layer]);
-                } else {
-                    processor.apply(this, [layer, childNode]);
+            },
+            "DescribeLayer": function(node, obj) {
+                obj.describelayer = {formats: []};
+                this.readChildNodes(node, obj.describelayer);
+            },
+            "GetLegendGraphic": function(node, obj) {
+                obj.getlegendgraphic = {formats: []};
+                this.readChildNodes(node, obj.getlegendgraphic);
+            },
+            "GetStyles": function(node, obj) {
+                obj.getstyles = {formats: []};
+                this.readChildNodes(node, obj.getstyles);
+            },
+            "PutStyles": function(node, obj) {
+                obj.putstyles = {formats: []};
+                this.readChildNodes(node, obj.putstyles);
+            },
+            "UserDefinedSymbolization": function(node, obj) {
+                var userSymbols = {
+                    supportSLD: parseInt(node.getAttribute("SupportSLD")) == 1,
+                    userLayer: parseInt(node.getAttribute("UserLayer")) == 1,
+                    userStyle: parseInt(node.getAttribute("UserStyle")) == 1,
+                    remoteWFS: parseInt(node.getAttribute("RemoteWFS")) == 1
+                };
+                obj.userSymbols = userSymbols;
+            },
+            "LatLonBoundingBox": function(node, obj) {
+                obj.llbbox = [
+                    parseFloat(node.getAttribute("minx")),
+                    parseFloat(node.getAttribute("miny")),
+                    parseFloat(node.getAttribute("maxx")),
+                    parseFloat(node.getAttribute("maxy"))
+                ];
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+                bbox.srs  = node.getAttribute("SRS");
+                obj.bbox[bbox.srs] = bbox;
+            },
+            "ScaleHint": function(node, obj) {
+                var min = node.getAttribute("min");
+                var max = node.getAttribute("max");
+                var rad2 = Math.pow(2, 0.5);
+                var ipm = OpenLayers.INCHES_PER_UNIT["m"];
+                obj.maxScale = parseFloat(
+                    ((min / rad2) * ipm * 
+                        OpenLayers.DOTS_PER_INCH).toPrecision(13)
+                );
+                obj.minScale = parseFloat(
+                    ((max / rad2) * ipm * 
+                        OpenLayers.DOTS_PER_INCH).toPrecision(13)
+                );
+            },
+            "Dimension": function(node, obj) {
+                var name = node.getAttribute("name").toLowerCase();
+                var dim = {
+                    name: name,
+                    units: node.getAttribute("units"),
+                    unitsymbol: node.getAttribute("unitSymbol")
+                };
+                obj.dimensions[dim.name] = dim;
+            },
+            "Extent": function(node, obj) {
+                var name = node.getAttribute("name").toLowerCase();
+                if (name in obj["dimensions"]) {
+                    var extent = obj.dimensions[name];
+                    extent.nearestVal = 
+                        node.getAttribute("nearestValue") === "1";
+                    extent.multipleVal = 
+                        node.getAttribute("multipleValues") === "1";
+                    extent.current = node.getAttribute("current") === "1";
+                    extent["default"] = node.getAttribute("default") || "";
+                    var values = this.getChildValue(node);
+                    extent.values = values.split(",");
                 }
-            }
-        }
-        if(layer.name) {
-            var index = layer.name.indexOf(":");
-            if(index > 0) {
-                layer.prefix = layer.name.substring(0, index);
-            }
-            capability.layers.push(layer);
-        }
+                }
+        }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])
     },
-    
-    /**
-     * Method: read_cap_ScaleHint
-     * The Layer ScaleHint element has min and max attributes that relate to
-     *     the minimum and maximum resolution that the server supports.  The
-     *     values are pixel diagonals measured in meters (on the ground).
-     */
-    read_cap_ScaleHint: function(layer, node) {
-        var min = node.getAttribute("min");
-        var max = node.getAttribute("max");
-        var rad2 = Math.pow(2, 0.5);
-        var ipm = OpenLayers.INCHES_PER_UNIT["m"];
-        layer.maxScale = parseFloat(
-            ((rad2 * min) * ipm * OpenLayers.DOTS_PER_INCH).toPrecision(13)
-        );
-        layer.minScale = parseFloat(
-            ((rad2 * max) * ipm * OpenLayers.DOTS_PER_INCH).toPrecision(13)
-        );
-    },
-    
-    /**
-     * Method: read_cap_Name
-     */
-    read_cap_Name: function(obj, node) {
-        var name = this.getChildValue(node);
-        if(name) {
-            obj.name = name;
-        }
-    },
 
-    /**
-     * Method: read_cap_Title
-     */
-    read_cap_Title: function(obj, node) {
-        var title = this.getChildValue(node);
-        if(title) {
-            obj.title = title;
-        }
-    },
-
-    /**
-     * Method: read_cap_Abstract
-     */
-    read_cap_Abstract: function(obj, node) {
-        var abst = this.getChildValue(node);
-        if(abst) {
-            obj["abstract"] = abst;
-        }
-    },
-    
-    /**
-     * Method: read_cap_LatLonBoundingBox
-     */
-    read_cap_LatLonBoundingBox: function(layer, node) {
-        layer.llbbox = [
-            parseFloat(node.getAttribute("minx")),
-            parseFloat(node.getAttribute("miny")),
-            parseFloat(node.getAttribute("maxx")),
-            parseFloat(node.getAttribute("maxy"))
-        ];
-    },
-
-    /**
-     * Method: read_cap_Style
-     */
-    read_cap_Style: function(layer, node) {
-        var style = {};
-        this.runChildNodes(style, node);
-        layer.styles.push(style);
-    },
-
-    /**
-     * Method: read_cap_LegendURL
-     */
-    read_cap_LegendURL: function(style, node) {
-        var legend = {
-            width: node.getAttribute('width'),
-            height: node.getAttribute('height')
-        };
-        var links = node.getElementsByTagName("OnlineResource");
-        if(links.length > 0) {
-            this.read_cap_OnlineResource(legend, links[0]);
-        }
-        style.legend = legend;
-    },
-    
-    /**
-     * Method: read_cap_OnlineResource
-     */
-    read_cap_OnlineResource: function(obj, node) {
-        obj.href = this.getAttributeNS(
-            node, "http://www.w3.org/1999/xlink", "href"
-        );
-    },
-
     CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1" 
 
-});
\ No newline at end of file
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WMSCapabilities/v1_1.js
  */
@@ -32,6 +37,26 @@
         );
     },
 
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "SRS": function(node, obj) {
+                var srs = this.getChildValue(node);
+                var values = srs.split(/ +/);
+                for (var i=0, len=values.length; i<len; i++) {
+                    obj.srs[values[i]] = true;
+                }
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+    },
+
     CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_0" 
 
-});
\ No newline at end of file
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Format/WMSCapabilities/v1_1.js
  */
@@ -32,6 +37,22 @@
         );
     },
 
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "SRS": function(node, obj) {
+                obj.srs[this.getChildValue(node)] = true;
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+    },
+
     CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1" 
 
 });

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,128 @@
+/* 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/Format/WMSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3
+ * Abstract base class for WMS Capabilities version 1.3.X. 
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, 
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1, {
+    
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {
+        "wms": OpenLayers.Util.applyDefaults({
+            "WMS_Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "LayerLimit": function(node, obj) {
+                obj.layerLimit = parseInt(this.getChildValue(node));
+            },
+            "MaxWidth": function(node, obj) {
+                obj.maxWidth = parseInt(this.getChildValue(node));
+            },
+            "MaxHeight": function(node, obj) {
+                obj.maxHeight = parseInt(this.getChildValue(node));
+            },
+            "BoundingBox": function(node, obj) {
+                var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+                bbox.srs  = node.getAttribute("CRS");
+                obj.bbox[bbox.srs] = bbox;
+            },
+            "CRS": function(node, obj) {
+                // CRS is the synonym of SRS
+                this.readers.wms.SRS.apply(this, [node, obj]); 
+            },
+            "EX_GeographicBoundingBox": function(node, obj) {
+                // replacement of LatLonBoundingBox
+                obj.llbbox = [];
+                this.readChildNodes(node, obj.llbbox);
+                
+            },
+            "westBoundLongitude": function(node, obj) {
+                obj[0] = this.getChildValue(node);
+            },
+            "eastBoundLongitude": function(node, obj) {
+                obj[2] = this.getChildValue(node);
+            },
+            "southBoundLatitude": function(node, obj) {
+                obj[1] = this.getChildValue(node);
+            },
+            "northBoundLatitude": function(node, obj) {
+                obj[3] = this.getChildValue(node);
+            },
+            "MinScaleDenominator": function(node, obj) {
+                obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+            },
+            "MaxScaleDenominator": function(node, obj) {
+                obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+            },
+            "Dimension": function(node, obj) {
+                // dimension has extra attributes: default, multipleValues, 
+                // nearestValue, current which used to be part of Extent. It now
+                // also contains the values.
+                var name = node.getAttribute("name").toLowerCase();
+                var dim = {
+                    name: name,
+                    units: node.getAttribute("units"),
+                    unitsymbol: node.getAttribute("unitSymbol"),
+                    nearestVal: node.getAttribute("nearestValue") === "1",
+                    multipleVal: node.getAttribute("multipleValues") === "1",
+                    "default": node.getAttribute("default") || "",
+                    current: node.getAttribute("current") === "1",
+                    values: this.getChildValue(node).split(",")
+                    
+                };
+                // Theoretically there can be more dimensions with the same
+                // name, but with a different unit. Until we meet such a case,
+                // let's just keep the same structure as the WMS 1.1 
+                // GetCapabilities parser uses. We will store the last
+                // one encountered.
+                obj.dimensions[dim.name] = dim;
+            },
+            "Keyword": function(node, obj) {
+                // TODO: should we change the structure of keyword in v1.js?
+                // Make it an object with a value instead of a string?
+                var keyword = {value: this.getChildValue(node), 
+                    vocabulary: node.getAttribute("vocabulary")};
+                if (obj.keywords) {
+                    obj.keywords.push(keyword);
+                }
+            }
+        }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),
+        "sld": {
+            "UserDefinedSymbolization": function(node, obj) {
+                this.readers.wms.UserDefinedSymbolization.apply(this, [node, obj]);
+                // add the two extra attributes
+                obj.userSymbols.inlineFeature = parseInt(node.getAttribute("InlineFeature")) == 1;
+                obj.userSymbols.remoteWCS = parseInt(node.getAttribute("RemoteWCS")) == 1;
+            },
+            "DescribeLayer": function(node, obj) {
+                this.readers.wms.DescribeLayer.apply(this, [node, obj]);
+            },
+            "GetLegendGraphic": function(node, obj) {
+                this.readers.wms.GetLegendGraphic.apply(this, [node, obj]);
+            }
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,30 @@
+/* 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/Format/WMSCapabilities/v1_3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3_0
+ * Read WMS Capabilities version 1.3.0. 
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic, 
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMSCapabilities.v1_3>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3_0 = OpenLayers.Class(
+    OpenLayers.Format.WMSCapabilities.v1_3, {
+    
+    /**
+     * Property: version
+     * {String} The specific parser version.
+     */
+    version: "1.3.0",
+    
+    CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3_0" 
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSCapabilities.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,10 @@
+/* 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/Format.js
+ * @requires OpenLayers/Format/XML.js
  */
 
 /**
@@ -7,7 +12,7 @@
  * Read WMS Capabilities.
  * 
  * Inherits from:
- *  - <OpenLayers.Format>
+ *  - <OpenLayers.Format.XML>
  */
 OpenLayers.Format.WMSCapabilities = OpenLayers.Class(OpenLayers.Format.XML, {
     
@@ -38,7 +43,7 @@
      *     this instance.
      */
     initialize: function(options) {
-        OpenLayers.Format.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
         this.options = options;
     },
 
@@ -65,9 +70,9 @@
             if(!constr) {
                 throw "Can't find a WMS capabilities parser for version " + version;
             }
-            var parser = new constr(this.options);
+            this.parser = new constr(this.options);
         }
-        var capabilities = parser.read(data);
+        var capabilities = this.parser.read(data);
         capabilities.version = version;
         return capabilities;
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -55,10 +56,12 @@
         var root = data.documentElement;
         var children = root.childNodes; 
         var describelayer = [];
+        var childNode, nodeName;
         for(var i=0; i<children.length; ++i) { 
             childNode = children[i];
             nodeName = childNode.nodeName; 
             if (nodeName == 'LayerDescription') {
+                var layerName = childNode.getAttribute('name');
                 var owsType = '';
                 var owsURL = '';
                 var typeName = '';
@@ -77,7 +80,7 @@
                     }
                 }
                 // look for Query child
-                query = childNode.getElementsByTagName('Query');
+                var query = childNode.getElementsByTagName('Query');
                 if(query.length > 0) {
                     typeName = query[0].getAttribute('typeName');
                     if (!typeName) {
@@ -85,7 +88,8 @@
                         typeName = query[0].getAttribute('typename');
                     }
                 }
-                describelayer.push({owsType: owsType, owsURL: owsURL, typeName: typeName}); 
+                describelayer.push({layerName: layerName, owsType: owsType, 
+                    owsURL: owsURL, typeName: typeName}); 
             }
         }
         return describelayer;

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSDescribeLayer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSGetFeatureInfo.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSGetFeatureInfo.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMSGetFeatureInfo.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -121,10 +122,11 @@
                 if (featureNodes) {
                     for (var j = 0; j < featureNodes.length; j++) {
                         var featureNode = featureNodes[j];
-                        var geom = this.parseGeometry(featureNode);
+                        var geomInfo = this.parseGeometry(featureNode);
                         var attributes = this.parseAttributes(featureNode);
-                        var feature = new OpenLayers.Feature.Vector(geom, 
+                        var feature = new OpenLayers.Feature.Vector(geomInfo.geometry, 
                             attributes, null);
+                        feature.bounds = geomInfo.bounds;
                         feature.type = layerName;
                         response.push(feature);
                     }
@@ -228,7 +230,7 @@
         var attributes = {};
         if (node.nodeType == 1) {
             var children = node.childNodes;
-            n = children.length
+            var n = children.length;
             for (var i = 0; i < n; ++i) {
                 var child = children[i];
                 if (child.nodeType == 1) {
@@ -252,13 +254,14 @@
 
     /**
      * Method: parseGeometry
-     * Parse the geometry out of the node using Format.GML
+     * Parse the geometry and the feature bounds out of the node using 
+     *     Format.GML
      *
      * Parameters:
      * node - {<DOMElement>}
      *
      * Returns:
-     * {<OpenLayers.Geometry>} the geometry object
+     * {Object} An object containing the geometry and the feature bounds
     */
     parseGeometry: function(node) {
         // we need to use the old Format.GML parser since we do not know the 
@@ -267,12 +270,13 @@
             this.gmlFormat = new OpenLayers.Format.GML();
         }
         var feature = this.gmlFormat.parseFeature(node);
-        var geometry = null;
-        if (feature && feature.geometry) {
-            geometry = feature.geometry.clone();
+        var geometry, bounds = null;
+        if (feature) {
+            geometry = feature.geometry && feature.geometry.clone();
+            bounds = feature.bounds && feature.bounds.clone();
             feature.destroy();
         }
-        return geometry;
+        return {geometry: geometry, bounds: bounds};
     },
 
     CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo"

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,221 +0,0 @@
-/* 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/Format/WMTSCapabilities.js
- * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
- */
-
-/**
- * Class: OpenLayers.Format.WMTSCapabilities.v1_0_0
- * Read WMTS Capabilities version 1.0.0.
- * 
- * Inherits from:
- *  - <OpenLayers.Format.WMTSCapabilities>
- */
-OpenLayers.Format.WMTSCapabilities.v1_0_0 = OpenLayers.Class(
-    OpenLayers.Format.OWSCommon.v1_1_0, {
-        
-    /**
-     * Property: version
-     * {String} The parser version ("1.0.0").
-     */
-    version: "1.0.0",
-
-    /**
-     * Property: namespaces
-     * {Object} Mapping of namespace aliases to namespace URIs.
-     */
-    namespaces: {
-        ows: "http://www.opengis.net/ows/1.1",
-        wmts: "http://www.opengis.net/wmts/1.0",
-        xlink: "http://www.w3.org/1999/xlink"
-    },    
-    
-    /**
-     * Property: yx
-     * {Object} Members in the yx object are used to determine if a CRS URN
-     *     corresponds to a CRS with y,x axis order.  Member names are CRS URNs
-     *     and values are boolean.  Defaults come from the 
-     *     <OpenLayers.Format.WMTSCapabilities> prototype.
-     */
-    yx: null,
-
-    /**
-     * Property: defaultPrefix
-     * {String} The default namespace alias for creating element nodes.
-     */
-    defaultPrefix: "wmts",
-
-    /**
-     * Constructor: OpenLayers.Format.WMTSCapabilities.v1_0_0
-     * Create a new parser for WMTS capabilities version 1.0.0. 
-     *
-     * Parameters:
-     * options - {Object} An optional object whose properties will be set on
-     *     this instance.
-     */
-    initialize: function(options) {
-        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
-        this.options = options;
-        var yx = OpenLayers.Util.extend(
-            {}, OpenLayers.Format.WMTSCapabilities.prototype.yx
-        );
-        this.yx = OpenLayers.Util.extend(yx, this.yx);
-    },
-
-    /**
-     * APIMethod: read
-     * Read capabilities data from a string, and return info about the WMTS.
-     * 
-     * Parameters: 
-     * data - {String} or {DOMElement} data to read/parse.
-     *
-     * Returns:
-     * {Object} Information about the SOS service.
-     */
-    read: function(data) {
-        if(typeof data == "string") {
-            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
-        }
-        if(data && data.nodeType == 9) {
-            data = data.documentElement;
-        }
-        var capabilities = {};
-        this.readNode(data, capabilities);
-        capabilities.version = this.version;
-        return capabilities;
-    },
-
-    /**
-     * Property: readers
-     * Contains public functions, grouped by namespace prefix, that will
-     *     be applied when a namespaced node is found matching the function
-     *     name.  The function will be applied in the scope of this parser
-     *     with two arguments: the node being read and a context object passed
-     *     from the parent.
-     */
-    readers: {        
-        "wmts": {
-            "Capabilities": function(node, obj) {
-                this.readChildNodes(node, obj);
-            },
-            "Contents": function(node, obj) {
-                obj.contents = {};                
-                obj.contents.layers = [];
-                obj.contents.tileMatrixSets = {};                
-                this.readChildNodes(node, obj.contents);
-            },
-            "Layer": function(node, obj) {
-                var layer = {
-                    styles: [],
-                    formats: [],
-                    tileMatrixSetLinks: []
-                };
-                layer.layers = [];
-                this.readChildNodes(node, layer);
-                obj.layers.push(layer);
-            },
-            "Style": function(node, obj) {
-                var style = {};
-                style.isDefault = (node.getAttribute("isDefault") === "true");
-                this.readChildNodes(node, style);
-                obj.styles.push(style);
-            },
-            "Format": function(node, obj) {
-                obj.formats.push(this.getChildValue(node)); 
-            },
-            "TileMatrixSetLink": function(node, obj) {
-                var tileMatrixSetLink = {};
-                this.readChildNodes(node, tileMatrixSetLink);
-                obj.tileMatrixSetLinks.push(tileMatrixSetLink);
-            },
-            "TileMatrixSet": function(node, obj) {
-                // node could be child of wmts:Contents or wmts:TileMatrixSetLink
-                // duck type wmts:Contents by looking for layers
-                if (obj.layers) {
-                    // TileMatrixSet as object type in schema
-                    var tileMatrixSet = {
-                        matrixIds: []
-                    };
-                    this.readChildNodes(node, tileMatrixSet);
-                    obj.tileMatrixSets[tileMatrixSet.identifier] = tileMatrixSet;
-                } else {
-                    // TileMatrixSet as string type in schema
-                    obj.tileMatrixSet = this.getChildValue(node);
-                }
-            },
-            "TileMatrix": function(node, obj) {
-                var tileMatrix = {
-                    supportedCRS: obj.supportedCRS
-                };
-                this.readChildNodes(node, tileMatrix);
-                obj.matrixIds.push(tileMatrix);
-            },
-            "ScaleDenominator": function(node, obj) {
-                obj.scaleDenominator = parseFloat(this.getChildValue(node)); 
-            },
-            "TopLeftCorner": function(node, obj) {                
-                var topLeftCorner = this.getChildValue(node);
-                var coords = topLeftCorner.split(" ");
-                // decide on axis order for the given CRS
-                var yx;
-                if (obj.supportedCRS) {
-                    // extract out version from URN
-                    var crs = obj.supportedCRS.replace(
-                        /urn:ogc:def:crs:(\w+):.+:(\w+)$/, 
-                        "urn:ogc:def:crs:$1::$2"
-                    );
-                    yx = !!this.yx[crs];
-                }
-                if (yx) {
-                    obj.topLeftCorner = new OpenLayers.LonLat(
-                        coords[1], coords[0]
-                    );
-                } else {
-                    obj.topLeftCorner = new OpenLayers.LonLat(
-                        coords[0], coords[1]
-                    );
-                }
-            },
-            "TileWidth": function(node, obj) {
-                obj.tileWidth = parseInt(this.getChildValue(node)); 
-            },
-            "TileHeight": function(node, obj) {
-                obj.tileHeight = parseInt(this.getChildValue(node)); 
-            },
-            "MatrixWidth": function(node, obj) {
-                obj.matrixWidth = parseInt(this.getChildValue(node)); 
-            },
-            "MatrixHeight": function(node, obj) {
-                obj.matrixHeight = parseInt(this.getChildValue(node)); 
-            },        
-            // not used for now, can be added in the future though
-            /*"Themes": function(node, obj) {
-                obj.themes = [];
-                this.readChildNodes(node, obj.themes);
-            },
-            "Theme": function(node, obj) {
-                var theme = {};                
-                this.readChildNodes(node, theme);
-                obj.push(theme);
-            },*/
-            "WSDL": function(node, obj) {
-                obj.wsdl = {};
-                obj.wsdl.href = node.getAttribute("xlink:href");
-                // TODO: other attributes of <WSDL> element                
-            },
-            "ServiceMetadataURL": function(node, obj) {
-                obj.serviceMetadataUrl = {};
-                obj.serviceMetadataUrl.href = node.getAttribute("xlink:href");
-                // TODO: other attributes of <ServiceMetadataURL> element                
-            }            
-        },
-        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
-    },    
-    
-    CLASS_NAME: "OpenLayers.Format.WMTSCapabilities.v1_0_0" 
-
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,221 @@
+/* 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/Format/WMTSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities.v1_0_0
+ * Read WMTS Capabilities version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.WMTSCapabilities>
+ */
+OpenLayers.Format.WMTSCapabilities.v1_0_0 = OpenLayers.Class(
+    OpenLayers.Format.OWSCommon.v1_1_0, {
+        
+    /**
+     * Property: version
+     * {String} The parser version ("1.0.0").
+     */
+    version: "1.0.0",
+
+    /**
+     * Property: namespaces
+     * {Object} Mapping of namespace aliases to namespace URIs.
+     */
+    namespaces: {
+        ows: "http://www.opengis.net/ows/1.1",
+        wmts: "http://www.opengis.net/wmts/1.0",
+        xlink: "http://www.w3.org/1999/xlink"
+    },    
+    
+    /**
+     * Property: yx
+     * {Object} Members in the yx object are used to determine if a CRS URN
+     *     corresponds to a CRS with y,x axis order.  Member names are CRS URNs
+     *     and values are boolean.  Defaults come from the 
+     *     <OpenLayers.Format.WMTSCapabilities> prototype.
+     */
+    yx: null,
+
+    /**
+     * Property: defaultPrefix
+     * {String} The default namespace alias for creating element nodes.
+     */
+    defaultPrefix: "wmts",
+
+    /**
+     * Constructor: OpenLayers.Format.WMTSCapabilities.v1_0_0
+     * Create a new parser for WMTS capabilities version 1.0.0. 
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+        var yx = OpenLayers.Util.extend(
+            {}, OpenLayers.Format.WMTSCapabilities.prototype.yx
+        );
+        this.yx = OpenLayers.Util.extend(yx, this.yx);
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return info about the WMTS.
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Information about the SOS service.
+     */
+    read: function(data) {
+        if(typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        if(data && data.nodeType == 9) {
+            data = data.documentElement;
+        }
+        var capabilities = {};
+        this.readNode(data, capabilities);
+        capabilities.version = this.version;
+        return capabilities;
+    },
+
+    /**
+     * Property: readers
+     * Contains public functions, grouped by namespace prefix, that will
+     *     be applied when a namespaced node is found matching the function
+     *     name.  The function will be applied in the scope of this parser
+     *     with two arguments: the node being read and a context object passed
+     *     from the parent.
+     */
+    readers: {        
+        "wmts": {
+            "Capabilities": function(node, obj) {
+                this.readChildNodes(node, obj);
+            },
+            "Contents": function(node, obj) {
+                obj.contents = {};                
+                obj.contents.layers = [];
+                obj.contents.tileMatrixSets = {};                
+                this.readChildNodes(node, obj.contents);
+            },
+            "Layer": function(node, obj) {
+                var layer = {
+                    styles: [],
+                    formats: [],
+                    tileMatrixSetLinks: []
+                };
+                layer.layers = [];
+                this.readChildNodes(node, layer);
+                obj.layers.push(layer);
+            },
+            "Style": function(node, obj) {
+                var style = {};
+                style.isDefault = (node.getAttribute("isDefault") === "true");
+                this.readChildNodes(node, style);
+                obj.styles.push(style);
+            },
+            "Format": function(node, obj) {
+                obj.formats.push(this.getChildValue(node)); 
+            },
+            "TileMatrixSetLink": function(node, obj) {
+                var tileMatrixSetLink = {};
+                this.readChildNodes(node, tileMatrixSetLink);
+                obj.tileMatrixSetLinks.push(tileMatrixSetLink);
+            },
+            "TileMatrixSet": function(node, obj) {
+                // node could be child of wmts:Contents or wmts:TileMatrixSetLink
+                // duck type wmts:Contents by looking for layers
+                if (obj.layers) {
+                    // TileMatrixSet as object type in schema
+                    var tileMatrixSet = {
+                        matrixIds: []
+                    };
+                    this.readChildNodes(node, tileMatrixSet);
+                    obj.tileMatrixSets[tileMatrixSet.identifier] = tileMatrixSet;
+                } else {
+                    // TileMatrixSet as string type in schema
+                    obj.tileMatrixSet = this.getChildValue(node);
+                }
+            },
+            "TileMatrix": function(node, obj) {
+                var tileMatrix = {
+                    supportedCRS: obj.supportedCRS
+                };
+                this.readChildNodes(node, tileMatrix);
+                obj.matrixIds.push(tileMatrix);
+            },
+            "ScaleDenominator": function(node, obj) {
+                obj.scaleDenominator = parseFloat(this.getChildValue(node)); 
+            },
+            "TopLeftCorner": function(node, obj) {                
+                var topLeftCorner = this.getChildValue(node);
+                var coords = topLeftCorner.split(" ");
+                // decide on axis order for the given CRS
+                var yx;
+                if (obj.supportedCRS) {
+                    // extract out version from URN
+                    var crs = obj.supportedCRS.replace(
+                        /urn:ogc:def:crs:(\w+):.+:(\w+)$/, 
+                        "urn:ogc:def:crs:$1::$2"
+                    );
+                    yx = !!this.yx[crs];
+                }
+                if (yx) {
+                    obj.topLeftCorner = new OpenLayers.LonLat(
+                        coords[1], coords[0]
+                    );
+                } else {
+                    obj.topLeftCorner = new OpenLayers.LonLat(
+                        coords[0], coords[1]
+                    );
+                }
+            },
+            "TileWidth": function(node, obj) {
+                obj.tileWidth = parseInt(this.getChildValue(node)); 
+            },
+            "TileHeight": function(node, obj) {
+                obj.tileHeight = parseInt(this.getChildValue(node)); 
+            },
+            "MatrixWidth": function(node, obj) {
+                obj.matrixWidth = parseInt(this.getChildValue(node)); 
+            },
+            "MatrixHeight": function(node, obj) {
+                obj.matrixHeight = parseInt(this.getChildValue(node)); 
+            },        
+            // not used for now, can be added in the future though
+            /*"Themes": function(node, obj) {
+                obj.themes = [];
+                this.readChildNodes(node, obj.themes);
+            },
+            "Theme": function(node, obj) {
+                var theme = {};                
+                this.readChildNodes(node, theme);
+                obj.push(theme);
+            },*/
+            "WSDL": function(node, obj) {
+                obj.wsdl = {};
+                obj.wsdl.href = node.getAttribute("xlink:href");
+                // TODO: other attributes of <WSDL> element                
+            },
+            "ServiceMetadataURL": function(node, obj) {
+                obj.serviceMetadataUrl = {};
+                obj.serviceMetadataUrl.href = node.getAttribute("xlink:href");
+                // TODO: other attributes of <ServiceMetadataURL> element                
+            }            
+        },
+        "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+    },    
+    
+    CLASS_NAME: "OpenLayers.Format.WMTSCapabilities.v1_0_0" 
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Format/WMTSCapabilities.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/WMTSCapabilities.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,162 @@
+/* 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/Format/XML.js
+ */
+ 
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities
+ * Read WMTS Capabilities.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML, {
+    
+    /**
+     * APIProperty: defaultVersion
+     * {String} Version number to assume if none found.  Default is "1.0.0".
+     */
+    defaultVersion: "1.0.0",
+    
+    /**
+     * APIProperty: version
+     * {String} Specify a version string if one is known.
+     */
+    version: null,
+
+    /**
+     * Property: parser
+     * {<OpenLayers.Format>} A cached versioned format used for reading.
+     */
+    parser: null,
+    
+    /**
+     * APIProperty: yx
+     * {Object} Members in the yx object are used to determine if a CRS URN
+     *     corresponds to a CRS with y,x axis order.  Member names are CRS URNs
+     *     and values are boolean.  By default, the following CRS URN are 
+     *     assumed to correspond to a CRS with y,x axis order:
+     *
+     * * urn:ogc:def:crs:EPSG::4326
+     */
+    yx: {
+        "urn:ogc:def:crs:EPSG::4326": true
+    },
+
+    /**
+     * Constructor: OpenLayers.Format.WMTSCapabilities
+     * Create a new parser for WMTS capabilities.
+     *
+     * Parameters:
+     * options - {Object} An optional object whose properties will be set on
+     *     this instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+        this.options = options;
+    },
+
+    /**
+     * APIMethod: read
+     * Read capabilities data from a string, and return information about
+     * the service (offering and observedProperty mostly).
+     * 
+     * Parameters: 
+     * data - {String} or {DOMElement} data to read/parse.
+     *
+     * Returns:
+     * {Object} Info about the WMTS Capabilities
+     */
+    read: function(data) {
+        if (typeof data == "string") {
+            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+        }
+        var root = data.documentElement;
+        var version = this.version || root.getAttribute("version") || this.defaultVersion;
+        if (!this.parser || this.parser.version !== version) {
+            var constr = OpenLayers.Format.WMTSCapabilities[
+                "v" + version.replace(/\./g, "_")
+            ];
+            if (!constr) {
+                throw new Error("Can't find a WMTS capabilities parser for version " + version);
+            }
+            this.parser = new constr(this.options);
+        }
+        return this.parser.read(data);
+    },
+
+    /**
+     * APIMethod: createLayer
+     * Create a WMTS layer given a capabilities object.
+     *
+     * Parameters:
+     * capabilities - {Object} The object returned from a <read> call to this 
+     *     format.
+     * config - {Object} Configuration properties for the layer.  Defaults for
+     *     the layer will apply if not provided.
+     *
+     * Required config properties:
+     * layer - {String} The layer identifier.
+     * matrixSet - {String} The matrix set identifier.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.WMTS>} A properly configured WMTS layer.  Throws an
+     *     error if an incomplete config is provided.  Returns undefined if no
+     *     layer could be created with the provided config.
+     */ 
+    createLayer: function(capabilities, config) {
+        var layer;
+
+        // confirm required properties are supplied in config
+        var required = {
+            layer: true,
+            matrixSet: true
+        };
+        for (var prop in required) {
+            if (!(prop in config)) {
+                throw new Error("Missing property '" + prop + "' in layer configuration.");
+            }
+        }
+
+        var contents = capabilities.contents;
+        var matrixSet = contents.tileMatrixSets[config.matrixSet];
+
+        // find the layer definition with the given identifier
+        var layers = contents.layers;
+        var layerDef;
+        for (var i=0, ii=contents.layers.length; i<ii; ++i) {
+            if (contents.layers[i].identifier === config.layer) {
+                layerDef = contents.layers[i];
+                break;
+            }
+        }
+        
+        if (layerDef && matrixSet) {
+            // get the default style for the layer
+            var style;
+            for (var i=0, ii=layerDef.styles.length; i<ii; ++i) {
+                style = layerDef.styles[i];
+                if (style.isDefault) {
+                    break;
+                }
+            }
+            
+            layer = new OpenLayers.Layer.WMTS(
+                OpenLayers.Util.applyDefaults(config, {
+                    url: capabilities.operationsMetadata.GetTile.dcp.http.get,
+                    name: layerDef.title,
+                    style: style,
+                    matrixIds: matrixSet.matrixIds
+                })
+            );
+        }
+        return layer;
+    },
+    
+    CLASS_NAME: "OpenLayers.Format.WMTSCapabilities" 
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format/XML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format/XML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format/XML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -243,6 +244,9 @@
      */
     createTextNode: function(text) {
         var node;
+        if (typeof text !== "string") {
+            text = String(text);
+        }
         if(this.xmldom) {
             node = this.xmldom.createTextNode(text);
         } else {
@@ -568,9 +572,6 @@
         }
         var value = options.value;
         if(value != null) {
-            if(typeof value == "boolean") {
-                value = String(value);
-            }
             node.appendChild(this.createTextNode(value));
         }
         return node;
@@ -617,7 +618,7 @@
         if(!obj) {
             obj = {};
         }
-        var group = this.readers[this.namespaceAlias[node.namespaceURI]];
+        var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix];
         if(group) {
             var local = node.localName || node.nodeName.split(":").pop();
             var reader = group[local] || group["*"];

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Format.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Format.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Format.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Collection.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Collection.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Collection.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -63,6 +64,7 @@
     destroy: function () {
         this.components.length = 0;
         this.components = null;
+        OpenLayers.Geometry.prototype.destroy.apply(this, arguments);
     },
 
     /**
@@ -260,22 +262,67 @@
     /**
      * APIMethod: getCentroid
      *
+     * Compute the centroid for this geometry collection.
+     *
+     * Parameters:
+     * weighted - {Boolean} Perform the getCentroid computation recursively,
+     * returning an area weighted average of all geometries in this collection.
+     *
      * Returns:
      * {<OpenLayers.Geometry.Point>} The centroid of the collection
      */
-    getCentroid: function() {
-        return this.components.length && this.components[0].getCentroid();
-        /*
-        var centroid;
-        for (var i=0, len=this.components.length; i<len; i++) {
-            if (!centroid) {
-                centroid = this.components[i].getCentroid();
-            } else {
-                centroid.resize(this.components[i].getCentroid(), 0.5);
+    getCentroid: function(weighted) {
+        if (!weighted) {
+            return this.components.length && this.components[0].getCentroid();
+        }
+        var len = this.components.length;
+        if (!len) {
+            return false;
+        }
+        
+        var areas = [];
+        var centroids = [];
+        var areaSum = 0;
+        var minArea = Number.MAX_VALUE;
+        var component;
+        for (var i=0; i<len; ++i) {
+            component = this.components[i];
+            var area = component.getArea();
+            var centroid = component.getCentroid(true);
+            if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) {
+                continue;
             }
+            areas.push(area);
+            areaSum += area;
+            minArea = (area < minArea && area > 0) ? area : minArea;
+            centroids.push(centroid);
         }
-        return centroid;
-        */
+        len = areas.length;
+        if (areaSum === 0) {
+            // all the components in this collection have 0 area
+            // probably a collection of points -- weight all the points the same
+            for (var i=0; i<len; ++i) {
+                areas[i] = 1;
+            }
+            areaSum = areas.length;
+        } else {
+            // normalize all the areas where the smallest area will get
+            // a value of 1
+            for (var i=0; i<len; ++i) {
+                areas[i] /= minArea;
+            }
+            areaSum /= minArea;
+        }
+        
+        var xSum = 0, ySum = 0, centroid, area;
+        for (var i=0; i<len; ++i) {
+            centroid = centroids[i];
+            area = areas[i];
+            xSum += centroid.x * area;
+            ySum += centroid.y * area;
+        }
+        
+        return new OpenLayers.Geometry.Point(xSum/areaSum, ySum/areaSum);
     },
 
     /**
@@ -382,7 +429,7 @@
     distanceTo: function(geometry, options) {
         var edge = !(options && options.edge === false);
         var details = edge && options && options.details;
-        var result, best;
+        var result, best, distance;
         var min = Number.POSITIVE_INFINITY;
         for(var i=0, len=this.components.length; i<len; ++i) {
             result = this.components[i].distanceTo(geometry, options);

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Curve.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Curve.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Curve.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LineString.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LineString.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LineString.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -127,7 +128,7 @@
      */
     getSortedSegments: function() {
         var numSeg = this.components.length - 1;
-        var segments = new Array(numSeg);
+        var segments = new Array(numSeg), point1, point2;
         for(var i=0; i<numSeg; ++i) {
             point1 = this.components[i];
             point2 = this.components[i + 1];

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LinearRing.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LinearRing.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/LinearRing.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -190,7 +191,7 @@
      * {<OpenLayers.Geometry.Point>} The centroid of the collection
      */
     getCentroid: function() {
-        if ( this.components && (this.components.length > 2)) {
+        if (this.components && (this.components.length > 2)) {
             var sumX = 0.0;
             var sumY = 0.0;
             for (var i = 0; i < this.components.length - 1; i++) {
@@ -202,8 +203,10 @@
             var area = -1 * this.getArea();
             var x = sumX / (6 * area);
             var y = sumY / (6 * area);
+            return new OpenLayers.Geometry.Point(x, y);
+        } else {
+            return null;
         }
-        return new OpenLayers.Geometry.Point(x, y);
     },
 
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiLineString.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiLineString.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiLineString.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPoint.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPoint.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPoint.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPolygon.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPolygon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/MultiPolygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Point.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Point.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Point.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Polygon.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Polygon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Polygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Rectangle.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Rectangle.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Rectangle.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Surface.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Surface.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry/Surface.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Geometry.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Geometry.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Geometry.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
  
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Box.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Box.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Box.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -61,6 +62,17 @@
     },
 
     /**
+     * Method: destroy
+     */
+    destroy: function() {
+        if (this.dragHandler) {
+            this.dragHandler.destroy();
+            this.dragHandler = null;
+        }            
+        OpenLayers.Handler.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
      * Method: setMap
      */
     setMap: function (map) {
@@ -194,7 +206,7 @@
                 "border-top-width")) + parseInt(OpenLayers.Element.getStyle(
                 this.zoomBox, "border-bottom-width")) + 1;
             // all browsers use the new box model, except IE in quirks mode
-            var newBoxModel = OpenLayers.Util.getBrowserName() == "msie" ?
+            var newBoxModel = OpenLayers.BROWSER_NAME == "msie" ?
                 document.compatMode != "BackCompat" : true;
             this.boxCharacteristics = {
                 xOffset: xOffset,

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Click.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Click.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Click.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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/Handler.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Drag.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Drag.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Drag.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -83,6 +84,20 @@
      *     This is "private", and should be left alone.
      */
     timeoutId: null,
+    
+    /**
+     * APIProperty: documentDrag
+     * {Boolean} If set to true, the handler will also handle mouse moves when
+     *     the cursor has moved out of the map viewport. Default is false.
+     */
+    documentDrag: false,
+    
+    /**
+     * Property: documentEvents
+     * {<OpenLayers.Events>} Event instance for observing document events. Will
+     *     be set on mouseout if documentDrag is set to true.
+     */
+    documentEvents: null,
 
     /**
      * Constructor: OpenLayers.Handler.Drag
@@ -185,9 +200,9 @@
             OpenLayers.Event.stop(evt);
             
             if(!this.oldOnselectstart) {
-                this.oldOnselectstart = (document.onselectstart) ? document.onselectstart : function() { return true; };
-                document.onselectstart = function() {return false;};
+                this.oldOnselectstart = (document.onselectstart) ? document.onselectstart : OpenLayers.Function.True;
             }
+            document.onselectstart = OpenLayers.Function.False;
             
             propagate = !this.stopDown;
         } else {
@@ -210,6 +225,16 @@
      */
     mousemove: function (evt) {
         if (this.started && !this.timeoutId && (evt.xy.x != this.last.x || evt.xy.y != this.last.y)) {
+            if(this.documentDrag === true && this.documentEvents) {
+                if(evt.element === document) {
+                    this.adjustXY(evt);
+                    // do setEvent manually because the documentEvents are not
+                    // registered with the map
+                    this.setEvent(evt);
+                } else {
+                    this.destroyDocumentEvents();
+                }
+            }
             if (this.interval > 0) {
                 this.timeoutId = setTimeout(OpenLayers.Function.bind(this.removeTimeout, this), this.interval);
             }
@@ -218,7 +243,7 @@
             this.callback("move", [evt.xy]);
             if(!this.oldOnselectstart) {
                 this.oldOnselectstart = document.onselectstart;
-                document.onselectstart = function() {return false;};
+                document.onselectstart = OpenLayers.Function.False;
             }
             this.last = this.evt.xy;
         }
@@ -245,6 +270,10 @@
      */
     mouseup: function (evt) {
         if (this.started) {
+            if(this.documentDrag === true && this.documentEvents) {
+                this.adjustXY(evt);
+                this.destroyDocumentEvents();
+            }
             var dragged = (this.start != this.last);
             this.started = false;
             this.dragging = false;
@@ -273,20 +302,32 @@
      */
     mouseout: function (evt) {
         if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.div)) {
-            var dragged = (this.start != this.last);
-            this.started = false; 
-            this.dragging = false;
-            OpenLayers.Element.removeClass(
-                this.map.viewPortDiv, "olDragDown"
-            );
-            this.out(evt);
-            this.callback("out", []);
-            if(dragged) {
-                this.callback("done", [evt.xy]);
+            if(this.documentDrag === true) {
+                this.documentEvents = new OpenLayers.Events(this, document,
+                                            null, null, {includeXY: true});
+                this.documentEvents.on({
+                    mousemove: this.mousemove,
+                    mouseup: this.mouseup
+                });
+                OpenLayers.Element.addClass(
+                    document.body, "olDragDown"
+                );
+            } else {
+                var dragged = (this.start != this.last);
+                this.started = false; 
+                this.dragging = false;
+                OpenLayers.Element.removeClass(
+                    this.map.viewPortDiv, "olDragDown"
+                );
+                this.out(evt);
+                this.callback("out", []);
+                if(dragged) {
+                    this.callback("done", [evt.xy]);
+                }
+                if(document.onselectstart) {
+                    document.onselectstart = this.oldOnselectstart;
+                }
             }
-            if(document.onselectstart) {
-                document.onselectstart = this.oldOnselectstart;
-            }
         }
         return true;
     },
@@ -345,6 +386,35 @@
         }
         return deactivated;
     },
+    
+    /**
+     * Method: adjustXY
+     * Converts event coordinates that are relative to the document body to
+     * ones that are relative to the map viewport. The latter is the default in
+     * OpenLayers.
+     * 
+     * Parameters:
+     * evt - {Object}
+     */
+    adjustXY: function(evt) {
+        var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv);
+        evt.xy.x -= pos[0];
+        evt.xy.y -= pos[1];
+    },
+    
+    /**
+     * Method: destroyDocumentEvents
+     * Destroys the events instance that gets added to the document body when
+     * documentDrag is true and the mouse cursor leaves the map viewport while
+     * dragging.
+     */
+    destroyDocumentEvents: function() {
+        OpenLayers.Element.removeClass(
+            document.body, "olDragDown"
+        );
+        this.documentEvents.destroy();
+        this.documentEvents = null;
+    },
 
     CLASS_NAME: "OpenLayers.Handler.Drag"
 });

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Feature.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Feature.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Feature.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Hover.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Hover.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Hover.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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/Handler.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Keyboard.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Keyboard.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Keyboard.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/MouseWheel.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/MouseWheel.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/MouseWheel.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -29,6 +30,32 @@
     mousePosition: null,
 
     /**
+     * Property: interval
+     * {Integer} In order to increase server performance, an interval (in 
+     *     milliseconds) can be set to reduce the number of up/down events 
+     *     called. If set, a new up/down event will not be set until the 
+     *     interval has passed. 
+     *     Defaults to 0, meaning no interval. 
+     */
+    interval: 0,
+    
+    /**
+     * Property: delta
+     * {Integer} When interval is set, delta collects the mousewheel z-deltas
+     *     of the events that occur within the interval.
+     *      See also the cumulative option
+     */
+    delta: 0,
+    
+    /**
+     * Property: cumulative
+     * {Boolean} When interval is set: true to collect all the mousewheel 
+     *     z-deltas, false to only record the delta direction (positive or
+     *     negative)
+     */
+    cumulative: true,
+
+    /**
      * Constructor: OpenLayers.Handler.MouseWheel
      *
      * Parameters:
@@ -138,7 +165,31 @@
         //
         if (!overScrollableDiv && overMapDiv) {
             if (overLayerDiv) {
-                this.wheelZoom(e);
+                var delta = 0;
+                if (!e) {
+                    e = window.event;
+                }
+                if (e.wheelDelta) {
+                    delta = e.wheelDelta/120; 
+                    if (window.opera && window.opera.version() < 9.2) {
+                        delta = -delta;
+                    }
+                } else if (e.detail) {
+                    delta = -e.detail / 3;
+                }
+                this.delta = this.delta + delta;
+
+                if(this.interval) {
+                    window.clearTimeout(this._timeoutId);
+                    this._timeoutId = window.setTimeout(
+                        OpenLayers.Function.bind(function(){
+                            this.wheelZoom(e);
+                        }, this),
+                        this.interval
+                    );
+                } else {
+                    this.wheelZoom(e);
+                }
             }
             OpenLayers.Event.stop(e);
         }
@@ -153,19 +204,9 @@
      * e - {Event}
      */
     wheelZoom: function(e) {
+        var delta = this.delta;
+        this.delta = 0;
         
-        var delta = 0;
-        if (!e) {
-            e = window.event;
-        }
-        if (e.wheelDelta) {
-            delta = e.wheelDelta/120; 
-            if (window.opera && window.opera.version() < 9.2) {
-                delta = -delta;
-            }
-        } else if (e.detail) {
-            delta = -e.detail / 3;
-        }
         if (delta) {
             // add the mouse position to the event because mozilla has 
             // a bug with clientX and clientY (see 
@@ -185,9 +226,9 @@
                 );
             }
             if (delta < 0) {
-               this.callback("down", [e, delta]);
+                this.callback("down", [e, this.cumulative ? delta : -1]);
             } else {
-               this.callback("up", [e, delta]);
+                this.callback("up", [e, this.cumulative ? delta : 1]);
             }
         }
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Path.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Path.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Path.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -275,11 +276,21 @@
         }
         return true;
     },
+
+    /**
+     * APIMethod: finishGeometry
+     * Finish the geometry and send it back to the control.
+     */
+    finishGeometry: function() {
+        var index = this.line.geometry.components.length - 1;
+        this.line.geometry.removeComponent(this.line.geometry.components[index]);
+        this.removePoint();
+        this.finalize();
+    },
   
     /**
      * Method: dblclick 
-     * Handle double-clicks.  Finish the geometry and send it back
-     * to the control.
+     * Handle double-clicks.
      * 
      * Parameters:
      * evt - {Event} The browser event
@@ -289,10 +300,7 @@
      */
     dblclick: function(evt) {
         if(!this.freehandMode(evt)) {
-            var index = this.line.geometry.components.length - 1;
-            this.line.geometry.removeComponent(this.line.geometry.components[index]);
-            this.removePoint();
-            this.finalize();
+            this.finishGeometry();
         }
         return false;
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Point.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Point.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Point.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -35,7 +36,7 @@
     layer: null,
     
     /**
-     * Property: multi
+     * APIProperty: multi
      * {Boolean} Cast features to multi-part geometries before passing to the
      *     layer.  Default is false.
      */
@@ -125,7 +126,7 @@
             // without this, resolution properties must be specified at the
             // map-level for this temporary layer to init its resolutions
             // correctly
-            calculateInRange: function() { return true; }
+            calculateInRange: OpenLayers.Function.True
         }, this.layerOptions);
         this.layer = new OpenLayers.Layer.Vector(this.CLASS_NAME, options);
         this.map.addLayer(this.layer);

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/Polygon.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/Polygon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/Polygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -19,7 +20,21 @@
  */
 OpenLayers.Handler.Polygon = OpenLayers.Class(OpenLayers.Handler.Path, {
     
+    /** 
+     * APIProperty: holeModifier
+     * {String} Key modifier to trigger hole digitizing.  Acceptable values are
+     *     "altKey", "shiftKey", or "ctrlKey".  If not set, no hole digitizing
+     *     will take place.  Default is null.
+     */
+    holeModifier: null,
+    
     /**
+     * Property: drawingHole
+     * {Boolean} Currently drawing an interior ring.
+     */
+    drawingHole: false,
+    
+    /**
      * Parameter: polygon
      * {<OpenLayers.Feature.Vector>}
      */
@@ -67,15 +82,152 @@
         this.line = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.LinearRing([this.point.geometry])
         );
-        this.polygon = new OpenLayers.Feature.Vector(
-            new OpenLayers.Geometry.Polygon([this.line.geometry])
-        );
+        
+        // check for hole digitizing
+        var polygon;
+        if (this.holeModifier && (this.evt[this.holeModifier])) {
+            var geometry = this.point.geometry;
+            var features = this.control.layer.features;
+            var candidate;
+            // look for intersections, last drawn gets priority
+            for (var i=features.length-1; i>=0; --i) {
+                candidate = features[i].geometry;
+                if ((candidate instanceof OpenLayers.Geometry.Polygon || 
+                    candidate instanceof OpenLayers.Geometry.MultiPolygon) && 
+                    candidate.intersects(geometry)) {
+                    polygon = features[i];
+                    this.control.layer.removeFeatures([polygon], {silent: true});
+                    this.control.layer.events.registerPriority(
+                        "sketchcomplete", this, this.finalizeInteriorRing
+                    );
+                    this.control.layer.events.registerPriority(
+                        "sketchmodified", this, this.enforceTopology
+                    );
+                    polygon.geometry.addComponent(this.line.geometry);
+                    this.polygon = polygon;
+                    this.drawingHole = true;
+                    break;
+                }
+            }
+        }
+        if (!polygon) {
+            this.polygon = new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Polygon([this.line.geometry])
+            );
+        }
+        
         this.callback("create", [this.point.geometry, this.getSketch()]);
         this.point.geometry.clearBounds();
         this.layer.addFeatures([this.polygon, this.point], {silent: true});
     },
+    
+    /**
+     * Method: enforceTopology
+     * Simple topology enforcement for drawing interior rings.  Ensures vertices
+     *     of interior rings are contained by exterior ring.  Other topology 
+     *     rules are enforced in <finalizeInteriorRing> to allow drawing of 
+     *     rings that intersect only during the sketch (e.g. a "C" shaped ring
+     *     that nearly encloses another ring).
+     */
+    enforceTopology: function(event) {
+        var point = event.vertex;
+        var components = this.line.geometry.components;
+        // ensure that vertices of interior ring are contained by exterior ring
+        if (!this.polygon.geometry.intersects(point)) {
+            var last = components[components.length-3];
+            point.x = last.x;
+            point.y = last.y;
+        }
+    },
+    
+    /**
+     * Method: finalizeInteriorRing
+     * Enforces that new ring has some area and doesn't contain vertices of any
+     *     other rings.
+     */
+    finalizeInteriorRing: function() {
+        var ring = this.line.geometry;
+        // ensure that ring has some area
+        var modified = (ring.getArea() !== 0);
+        if (modified) {
+            // ensure that new ring doesn't intersect any other rings
+            var rings = this.polygon.geometry.components;
+            for (var i=rings.length-2; i>=0; --i) {
+                if (ring.intersects(rings[i])) {
+                    modified = false;
+                    break;
+                }
+            }
+            if (modified) {
+                // ensure that new ring doesn't contain any other rings
+                var target;
+                outer: for (var i=rings.length-2; i>0; --i) {
+                    points = rings[i].components;
+                    for (var j=0, jj=points.length; j<jj; ++j) {
+                        if (ring.containsPoint(points[j])) {
+                            modified = false;
+                            break outer;
+                        }
+                    }
+                }
+            }
+        }
+        if (modified) {
+            if (this.polygon.state !== OpenLayers.State.INSERT) {
+                this.polygon.state = OpenLayers.State.UPDATE;
+            }
+        } else {
+            this.polygon.geometry.removeComponent(ring);
+        }
+        this.restoreFeature();
+        return false;
+    },
 
     /**
+     * APIMethod: cancel
+     * Finish the geometry and call the "cancel" callback.
+     */
+    cancel: function() {
+        if (this.drawingHole) {
+            this.polygon.geometry.removeComponent(this.line.geometry);
+            this.restoreFeature(true);
+        }
+        return OpenLayers.Handler.Path.prototype.cancel.apply(this, arguments);
+    },
+    
+    /**
+     * Method: restoreFeature
+     * Move the feature from the sketch layer to the target layer.
+     *
+     * Properties: 
+     * cancel - {Boolean} Cancel drawing.  If falsey, the "sketchcomplete" event
+     *     will be fired.
+     */
+    restoreFeature: function(cancel) {
+        this.control.layer.events.unregister(
+            "sketchcomplete", this, this.finalizeInteriorRing
+        );
+        this.control.layer.events.unregister(
+            "sketchmodified", this, this.enforceTopology
+        );
+        this.layer.removeFeatures([this.polygon], {silent: true});
+        this.control.layer.addFeatures([this.polygon], {silent: true});
+        this.drawingHole = false;
+        if (!cancel) {
+            // Re-trigger "sketchcomplete" so other listeners can do their
+            // business.  While this is somewhat sloppy (if a listener is 
+            // registered with registerPriority - not common - between the start
+            // and end of a single ring drawing - very uncommon - it will be 
+            // called twice).
+            // TODO: In 3.0, collapse sketch handlers into geometry specific
+            // drawing controls.
+            this.control.layer.events.triggerEvent(
+                "sketchcomplete", {feature : this.polygon}
+            );
+        }
+    },
+
+    /**
      * Method: destroyFeature
      * Destroy temporary geometries
      */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler/RegularPolygon.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler/RegularPolygon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler/RegularPolygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -56,6 +57,12 @@
     snapToggle: 'shiftKey',
     
     /**
+     * Property: layerOptions
+     * {Object} Any optional properties to be set on the sketch layer.
+     */
+    layerOptions: null,
+
+    /**
      * APIProperty: persist
      * {Boolean} Leave the feature rendered until clear is called.  Default
      *     is false.  If set to true, the feature remains rendered until
@@ -130,11 +137,13 @@
      *     cancel callback will receive a geometry.
      */
     initialize: function(control, callbacks, options) {
-        this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        if(!(options && options.layerOptions && options.layerOptions.styleMap)) {
+            this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        }
 
         OpenLayers.Handler.prototype.initialize.apply(this,
                                                 [control, callbacks, options]);
-        this.options = (options) ? options : new Object();
+        this.options = (options) ? options : {};
     },
     
     /**
@@ -159,14 +168,14 @@
         var activated = false;
         if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
             // create temporary vector layer for rendering geometry sketch
-            var options = {
+            var options = OpenLayers.Util.extend({
                 displayInLayerSwitcher: false,
                 // indicate that the temp vector layer will never be out of range
                 // without this, resolution properties must be specified at the
                 // map-level for this temporary layer to init its resolutions
                 // correctly
-                calculateInRange: function() { return true; }
-            };
+                calculateInRange: OpenLayers.Function.True
+            }, this.layerOptions);
             this.layer = new OpenLayers.Layer.Vector(this.CLASS_NAME, options);
             this.map.addLayer(this.layer);
             activated = true;
@@ -318,7 +327,7 @@
      * Modify the polygon geometry in place.
      */
     modifyGeometry: function() {
-        var angle, dx, dy, point;
+        var angle, point;
         var ring = this.feature.geometry.components[0];
         // if the number of sides ever changes, create a new geometry
         if(ring.components.length != (this.sides + 1)) {
@@ -379,8 +388,10 @@
      *     is true).
      */
     clear: function() {
-        this.layer.renderer.clear();
-        this.layer.destroyFeatures();
+        if (this.layer) {
+            this.layer.renderer.clear();
+            this.layer.destroyFeatures();
+        }
     },
     
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Handler.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Handler.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Handler.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -91,7 +92,8 @@
      * Parameters:
      * control - {<OpenLayers.Control>} The control that initialized this
      *     handler.  The control is assumed to have a valid map property; that
-     *     map is used in the handler's own setMap method.
+     *     map is used in the handler's own setMap method.  If a map property
+     *     is present in the options argument it will be used instead.
      * callbacks - {Object} An object whose properties correspond to abstracted
      *     events or sequences of browser events.  The values for these
      *     properties are functions defined by the control that get called by
@@ -103,11 +105,11 @@
         OpenLayers.Util.extend(this, options);
         this.control = control;
         this.callbacks = callbacks;
-        if (control.map) {
-            this.setMap(control.map); 
+
+        var map = this.map || control.map;
+        if (map) {
+            this.setMap(map); 
         }
-
-        OpenLayers.Util.extend(this, options);
         
         this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Icon.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Icon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Icon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,8 +1,8 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
-
 /**
  * Class: OpenLayers.Icon
  * 

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ar.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/ar.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ar.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ar.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,38 @@
+/* Translators (2009 onwards):
+ *  - Meno25
+ *  - Mutarjem horr
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["ar"]
+ * Dictionary for العربية.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["ar"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "وصلة دائمة",
+
+    'baseLayer': "الطبقة الاساسية",
+
+    'readNotImplemented': "القراءة غير محققة.",
+
+    'writeNotImplemented': "الكتابة غير محققة",
+
+    'errorLoadingGML': "خطأ عند تحميل الملف جي ام ال ${url}",
+
+    'scale': "النسبة = 1 : ${scaleDenom}",
+
+    'W': "غ",
+
+    'E': "شر",
+
+    'N': "شم",
+
+    'S': "ج"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/be-tarask.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/be-tarask.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/be-tarask.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/be-tarask.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+/* Translators (2009 onwards):
+ *  - EugeneZelenko
+ *  - Jim-by
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["be-tarask"]
+ * Dictionary for Беларуская (тарашкевіца).  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["be-tarask"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Неапрацаваны вынік запыту ${statusText}",
+
+    'permalink': "Сталая спасылка",
+
+    'overlays': "Слаі",
+
+    'baseLayer': "Базавы слой",
+
+    'sameProjection': "Аглядная мапа працуе толькі калі яна мае тую ж праекцыю, што і асноўная мапа",
+
+    'readNotImplemented': "Функцыянальнасьць чытаньня ня створаная.",
+
+    'writeNotImplemented': "Функцыянальнасьць запісу ня створаная.",
+
+    'noFID': "Немагчыма абнавіць магчымасьць, для якога не існуе FID.",
+
+    'errorLoadingGML': "Памылка загрузкі файла GML ${url}",
+
+    'browserNotSupported': "Ваш браўзэр не падтрымлівае вэктарную графіку. У цяперашні момант падтрымліваюцца: ${renderers}",
+
+    'componentShouldBe': "addFeatures : кампанэнт павінен быць ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent выкліканы для слоя бяз рэндэру. Звычайна гэта азначае, што Вы зьнішчылі слой, але пакінулі зьвязаны зь ім апрацоўшчык.",
+
+    'minZoomLevelError': "Уласьцівасьць minZoomLevel прызначана толькі для выкарыстаньня са слаямі вытворнымі ад FixedZoomLevels. Тое, што  гэты wfs-слой правяраецца на minZoomLevel — рэха прошлага. Але мы ня можам выдаліць гэтую магчымасьць, таму што ад яе залежаць некаторыя заснаваныя на OL дастасаваньні. Тым ня менш, праверка minZoomLevel будзе выдаленая ў вэрсіі 3.0. Калі ласка, выкарыстоўваеце замест яе ўстаноўкі мінімальнага/максымальнага памераў, як апісана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS-транзакцыя: ПОСЬПЕХ ${response}",
+
+    'commitFailed': "WFS-транзакцыя: ПАМЫЛКА ${response}",
+
+    'googleWarning': "Не атрымалася загрузіць слой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3e Хутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі Google Maps ня быў уключаныя альбо не ўтрымлівае слушны API-ключ для Вашага сайта.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",
+
+    'getLayerWarning': "Немагчыма загрузіць слой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі ${layerLib} ня быў слушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",
+
+    'scale': "Маштаб = 1 : ${scaleDenom}",
+
+    'W': "З",
+
+    'E': "У",
+
+    'N': "Пн",
+
+    'S': "Пд",
+
+    'layerAlreadyAdded': "Вы паспрабавалі дадаць слой ${layerName} на мапу, але ён ужо дададзены",
+
+    'reprojectDeprecated': "Вы выкарыстоўваеце ўстаноўку \'reproject\' для слоя ${layerName}. Гэтая ўстаноўка зьяўляецца састарэлай: яна выкарыстоўвалася для падтрымкі паказу зьвестак на камэрцыйных базавых мапах, але гэта функцыя цяпер рэалізаваная ў убудаванай падтрымцы сфэрычнай праекцыі Мэркатара. Дадатковая інфармацыя ёсьць на http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Гэты мэтад састарэлы і будзе выдалены ў вэрсіі 3.0. Калі ласка, замест яго выкарыстоўвайце ${newMethod}.",
+
+    'boundsAddError': "Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",
+
+    'lonlatAddError': "Вам неабходна падаць абодва значэньні lon і lat для функцыі складаньня.",
+
+    'pixelAddError': "Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",
+
+    'unsupportedGeometryType': "Тып геамэтрыі не падтрымліваецца: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition failed: верагодна элемэнт з ідэнтыфікатарам ${elemId} займае няслушнае месца.",
+
+    'filterEvaluateNotImplemented': "evaluate не рэалізаваны для гэтага тыпу фільтру."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/bg.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/bg.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/bg.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/bg.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,29 @@
+/* Translators (2009 onwards):
+ *  - DCLXVI
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["bg"]
+ * Dictionary for Български.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["bg"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "Постоянна препратка",
+
+    'baseLayer': "Основен слой",
+
+    'errorLoadingGML': "Грешка при зареждане на GML файл ${url}",
+
+    'scale': "Мащаб = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Опитахте да добавите слой ${layerName} в картата, но той вече е добавен",
+
+    'methodDeprecated': "Този метод е остарял и ще бъде премахват в 3.0. Вместо него използвайте ${newMethod}."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/br.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/br.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/br.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/br.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Fulup
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["br"]
+ * Dictionary for Brezhoneg.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["br"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Distro evel reked anveret ${statusText}",
+
+    'permalink': "Peurliamm",
+
+    'overlays': "Gwiskadoù",
+
+    'baseLayer': "Gwiskad diazez",
+
+    'sameProjection': "Ne\'z ar gartenn lec\'hiañ en-dro nemet pa vez heñvel ar banndres anezhi ha hini ar gartenn bennañ",
+
+    'readNotImplemented': "N\'eo ket emplementet al lenn.",
+
+    'writeNotImplemented': "N\'eo ket emplementet ar skrivañ.",
+
+    'noFID': "N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",
+
+    'errorLoadingGML': "Fazi e-ser kargañ ar restr GML ${url}",
+
+    'browserNotSupported': "N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",
+
+    'componentShouldBe': "addFeatures : bez\' e tlefe ar parzh besañ eus ar seurt ${geomType}",
+
+    'getFeatureError': "Galvet eo bet getFeatureFromEvent called war ur gwiskad hep daskorer. Kement-se a dalvez ez eus bet freuzet ur gwiskad hag hoc\'h eus miret un embreger bennak stag outañ.",
+
+    'minZoomLevelError': "Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Treuzgread WFS : MAT EO ${response}",
+
+    'commitFailed': "Treuzgread WFS Transaction: C\'HWITET ${response}",
+
+    'googleWarning': "N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",
+
+    'getLayerWarning': "N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",
+
+    'scale': "Skeul = 1 : ${scaleDenom}",
+
+    'W': "K",
+
+    'E': "R",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Klasket hoc\'h eus ouzhpennañ ar gwiskad : ${layerName} d\'ar gartenn, met ouzhpennet e oa bet c\'hoazh",
+
+    'reprojectDeprecated': "Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas.",
+
+    'boundsAddError': "Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",
+
+    'lonlatAddError': "Rekis eo tremen an div dalvoudenn hedred ha ledred d\'an arc\'hwel add.",
+
+    'pixelAddError': "Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",
+
+    'unsupportedGeometryType': "Seurt mentoniezh anskoret : ${geomType}",
+
+    'pagePositionFailed': "C\'hwitet eo OpenLayers.Util.pagePosition : marteze emañ lec\'hiet fall an elfenn id ${elemId}.",
+
+    'filterEvaluateNotImplemented': "N\'eo ket bet emplementet ar priziañ evit seurt siloù c\'hoazh."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ca.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ca.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ca.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */
@@ -14,16 +10,16 @@
  */
 OpenLayers.Lang.ca = {
 
-    'unhandledRequest': "Resposta a petició no gestionada ${statusText}",
+    'unhandledRequest': "Resposta a petició no gestionada ${statusText}",
 
-    'permalink': "Enllaç permanent",
+    'permalink': "Enllaç permanent",
 
     'overlays': "Capes addicionals",
 
     'baseLayer': "Capa Base",
 
     'sameProjection':
-        "El mapa de referència només funciona si té la mateixa projecció que el mapa principal",
+        "El mapa de referència només funciona si té la mateixa projecció que el mapa principal",
 
     'readNotImplemented': "Lectura no implementada.",
 
@@ -31,83 +27,90 @@
 
     'noFID': "No es pot actualitzar un element per al que no existeix FID.",
 
-    'errorLoadingGML': "Error caregant el fitxer GML ${url}",
+    'errorLoadingGML': "Error carregant el fitxer GML ${url}",
 
     'browserNotSupported':
-        "El seu navegador no suporta renderització vectorial. Els renderitzadors suportats actualmente són:\n${renderers}",
+        "El seu navegador no suporta renderització vectorial. Els renderitzadors suportats actualment són:\n${renderers}",
 
     'componentShouldBe': "addFeatures : el component ha de ser de tipus ${geomType}",
 
     // console message
     'getFeatureError':
-        "getFeatureFromEvent ha estat cridat a una capa sense renderizador. Això normalment vol dir que " +
-        "s'ha eliminat una capa, però no el handler associat a ella.",
+        "getFeatureFromEvent ha estat cridat des d'una capa sense renderizador. Això normalment vol dir que " +
+        "s'ha eliminat una capa, però no el handler associat a ella.",
 
     // console message
     'minZoomLevelError':
-        "La propietat minZoomLevel s'ha d'utilitzar només " +
+        "La propietat minZoomLevel s'ha d'utilitzar només " +
         "amb les capes que tenen FixedZoomLevels. El fet que " +
-        "una capa wfs comprovi minZoomLevel és una reliquia del " +
-        "passat. No podem, però, eliminar-la sense trencar " +
+        "una capa wfs comprovi minZoomLevel és una relíquia del " +
+        "passat. No podem, però, eliminar-la sense trencar " +
         "les aplicacions d'OpenLayers que en puguin dependre. " +
-        "Així doncs estem fent-la obsoleta -- la comprovació " +
-        "minZoomLevel s'eliminarà a la versió 3.0. Feu servir " +
-        "els paràmetres min/max resolution en substitució, tal com es descriu aquí: " +
+        "Així doncs estem fent-la obsoleta -- la comprovació " +
+        "minZoomLevel s'eliminarà a la versió 3.0. Feu servir " +
+        "els paràmetres min/max resolution en substitució, tal com es descriu aquí: " +
         "http://trac.openlayers.org/wiki/SettingZoomLevels",
 
-    'commitSuccess': "Transacció WFS: CORRECTA ${response}",
+    'commitSuccess': "Transacció WFS: CORRECTA ${response}",
 
-    'commitFailed': "Transacció WFS: HA FALLAT ${response}",
+    'commitFailed': "Transacció WFS: HA FALLAT ${response}",
 
     'googleWarning':
         "La capa Google no s'ha pogut carregar correctament.<br><br>" +
-        "Per evitar aquest missatge, sel·leccioneu una nova Capa Base " +
+        "Per evitar aquest missatge, seleccioneu una nova Capa Base " +
         "al gestor de capes de la cantonada superior dreta.<br><br>" +
-        "Probablement això és degut a que l'script de la biblioteca de " +
-    "Google Maps no ha estat inclòs a la vostra pàgina, o no " +
-    "conté la clau de l'API correcta per a la vostra adreça.<br><br>" +
-        "Desenvolupadors: Per obtenir consells sobre com fer anar això, " +
+        "Probablement això és degut a que l'script de la biblioteca de " +
+    "Google Maps no ha estat inclòs a la vostra pàgina, o no " +
+    "conté la clau de l'API correcta per a la vostra adreça.<br><br>" +
+        "Desenvolupadors: Per obtenir consells sobre com fer anar això, " +
         "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>féu clic aquí</a>",
+        "target='_blank'>féu clic aquí</a>",
 
     'getLayerWarning':
-        "Per evitar aquest missatge, sel·leccioneu una nova Capa Base " +
+        "Per evitar aquest missatge, seleccioneu una nova Capa Base " +
         "al gestor de capes de la cantonada superior dreta.<br><br>" +
-        "Probablement això és degut a que l'script de la biblioteca " +
+        "Probablement això és degut a que l'script de la biblioteca " +
         "${layerLib} " +
-        "no ha estat inclòs a la vostra pàgina.<br><br>" +
-        "Desenvolupadors: Per obtenir consells sobre com fer anar això, " +
+        "no ha estat inclòs a la vostra pàgina.<br><br>" +
+        "Desenvolupadors: Per obtenir consells sobre com fer anar això, " +
         "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>féu clic aquí</a>",
+        "target='_blank'>féu clic aquí</a>",
 
     'scale': "Escala = 1 : ${scaleDenom}",
 
+    //labels for the graticule control
+    'W': 'O',
+    'E': 'E',
+    'N': 'N',
+    'S': 'S',
+    'graticule': 'Retícula',    
+        
     // console message
     'layerAlreadyAdded':
-        "Heu intentat afegir la capa: ${layerName} al mapa, pero ja ha estat afegida anteriorment",
+        "Heu intentat afegir la capa: ${layerName} al mapa, però ja ha estat afegida anteriorment",
 
     // console message
     'reprojectDeprecated':
-        "Esteu fent servir l'opció 'reproject' a la capa " +
-        "${layerName}. Aquesta opció és obsoleta: el seu ús fou concebut " +
-        "per suportar la visualització de dades sobre mapes base comercials, " + 
-        "però aquesta funcionalitat s'hauria d'assolir ara mitjançant el suport " +
-        "de la projecció Spherical Mercator. Més informació disponible a " +
+        "Esteu fent servir l'opció 'reproject' a la capa " +
+        "${layerName}. Aquesta opció és obsoleta: el seu ús fou concebut " +
+        "per suportar la visualització de dades sobre mapes base comercials, " + 
+        "però ara aquesta funcionalitat s'hauria d'assolir mitjançant el suport " +
+        "de la projecció Spherical Mercator. Més informació disponible a " +
         "http://trac.openlayers.org/wiki/SphericalMercator.",
 
     // console message
     'methodDeprecated':
-        "Aquest mètode és obsolet i s'eliminará a la versió 3.0. " +
-        "Si us plau feu servir em mètode alternatiu ${newMethod}.",
+        "Aquest mètode és obsolet i s'eliminarà a la versió 3.0. " +
+        "Si us plau feu servir em mètode alternatiu ${newMethod}.",
 
     // console message
-    'boundsAddError': "Ha de proporcionar els valors x i y a la funció add.",
+    'boundsAddError': "Ha de proporcionar els valors x i y a la funció add.",
 
     // console message
-    'lonlatAddError': "Ha de proporcionar els valors lon i lat a la funció add.",
+    'lonlatAddError': "Ha de proporcionar els valors lon i lat a la funció add.",
 
     // console message
-    'pixelAddError': "Ha de proporcionar els valors x i y a la funció add.",
+    'pixelAddError': "Ha de proporcionar els valors x i y a la funció add.",
 
     // console message
     'unsupportedGeometryType': "Tipus de geometria no suportada: ${geomType}",
@@ -117,8 +120,9 @@
         "OpenLayers.Util.pagePosition ha fallat: l'element amb id ${elemId} pot estar fora de lloc.",
                     
     // console message
-    'filterEvaluateNotImplemented': "evaluate no està implementat per aquest tipus de filtre.",
+    'filterEvaluateNotImplemented': "evaluate no està implementat per aquest tipus de filtre.",
 
+    // **** end ****
     'end': ''
 
 };

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/cs-CZ.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/cs-CZ.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/cs-CZ.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,6 @@
-/* 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. */
+/* Translators (2009 onwards):
+ *  - Mormegil
+ */
 
 /**
  * @requires OpenLayers/Lang.js
@@ -8,22 +8,21 @@
 
 /**
  * Namespace: OpenLayers.Lang["cs-CZ"]
- * Dictionary for Czech.  Keys for entries are used in calls to
+ * Dictionary for ÄŒesky.  Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
-OpenLayers.Lang["cs-CZ"] = {
+OpenLayers.Lang["cs-CZ"] = OpenLayers.Util.applyDefaults({
 
     'unhandledRequest': "Nezpracovaná návratová hodnota ${statusText}",
 
-    'permalink': "Odkaz na aktuální mapu",
+    'permalink': "Trvalý odkaz",
 
     'overlays': "Překryvné vrstvy",
 
     'baseLayer': "Podkladové vrstvy",
 
-    'sameProjection':
-        "Přehledka pracuje správně pouze pokud je ve stejné projekci, jako hlavní mapa",
+    'sameProjection': "Přehledka pracuje správně pouze tehdy, pokud je ve stejné projekci jako hlavní mapa",
 
     'readNotImplemented': "Read není implementováno.",
 
@@ -33,88 +32,38 @@
 
     'errorLoadingGML': "Chyba při načítání souboru GML ${url}",
 
-    'browserNotSupported':
-        "Váš prohlížeč nepodporuje vykreslování vektorů. Momentálně podporované nástroje jsou::\n${renderers}",
+    'browserNotSupported': "Váš prohlížeč nepodporuje vykreslování vektorů. Momentálně podporované nástroje jsou::\n${renderers}",
 
     'componentShouldBe': "addFeatures : komponenta by měla být ${geomType}",
 
-    // console message
-    'getFeatureError':
-        "getFeatureFromEvent bylo zavoláno na vrstvě, která nemá vykreslovač. To obyčejně znamená, že " +
-        "jste odstranil vrstvu, ale ne rutinu s ní asociovanou.",
+    'getFeatureError': "getFeatureFromEvent bylo zavoláno na vrstvě, která nemá vykreslovač. To obyčejně znamená, že jste odstranil vrstvu, ale ne rutinu s ní asociovanou.",
 
-    // console message
-    'minZoomLevelError':
-        "Vlastnost minZoomLevel by se měla používat pouze " +
-        "s potomky FixedZoomLevels vrstvami. To znamená, že " +
-        "vrstva wfs kontroluje, zda-li minZoomLevel není zbytek z minulosti." +
-        "Nelze to ovšem vyjmout bez možnosti, že bychom rozbili " +
-        "aplikace postavené na OL, které by na tom mohly záviset. " +
-        "Proto tuto vlastnost nedoporučujeme používat --  kontrola minZoomLevel " +
-        "bude odstraněna ve verzi 3.0. Použijte prosím " +
-        "raději nastavení min/max podle příkaldu popsaného na: " +
-        "http://trac.openlayers.org/wiki/SettingZoomLevels",
+    'minZoomLevelError': "Vlastnost minZoomLevel by se měla používat pouze s potomky FixedZoomLevels vrstvami. To znamená, že vrstva wfs kontroluje, zda-li minZoomLevel není zbytek z minulosti.Nelze to ovšem vyjmout bez možnosti, že bychom rozbili aplikace postavené na OL, které by na tom mohly záviset. Proto tuto vlastnost nedoporučujeme používat --  kontrola minZoomLevel bude odstraněna ve verzi 3.0. Použijte prosím raději nastavení min/max podle příkaldu popsaného na: http://trac.openlayers.org/wiki/SettingZoomLevels",
 
     'commitSuccess': "WFS Transaction: ÚSPĚCH ${response}",
 
     'commitFailed': "WFS Transaction: CHYBA ${response}",
 
-    'googleWarning':
-        "Nepodařilo se správně načíst vrstvu Google.<br><br>" +
-        "Abyste se zbavili této zprávy, zvolte jinou základní vrstvu " +
-        "v přepínači vrstev.<br><br>" +
-        "To se většinou stává, pokud " +
-        "nebyl načten skript, nebo neobsahuje správný " +
-        "klíč pro API pro tuto stránku.<br><br>" +
-        "Vývojáři: Pro pomoc, aby tohle fungovalo , " +
-        "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>klikněte sem</a>",
+    'googleWarning': "Nepodařilo se správně načíst vrstvu Google.\x3cbr\x3e\x3cbr\x3eAbyste se zbavili této zprávy, zvolte jinou základní vrstvu v přepínači vrstev.\x3cbr\x3e\x3cbr\x3eTo se většinou stává, pokud nebyl načten skript, nebo neobsahuje správný klíč pro API pro tuto stránku.\x3cbr\x3e\x3cbr\x3eVývojáři: Pro pomoc, aby tohle fungovalo , \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklikněte sem\x3c/a\x3e",
 
-    'getLayerWarning':
-        "The ${layerType} Layer was unable to load correctly.<br><br>" +
-        "To get rid of this message, select a new BaseLayer " +
-        "in the layer switcher in the upper-right corner.<br><br>" +
-        "Most likely, this is because the ${layerLib} library " +
-        "script was either not correctly included.<br><br>" +
-        "Developers: For help getting this working correctly, " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>click here</a>",
+    'getLayerWarning': "The ${layerType} Layer was unable to load correctly.\x3cbr\x3e\x3cbr\x3eTo get rid of this message, select a new BaseLayer in the layer switcher in the upper-right corner.\x3cbr\x3e\x3cbr\x3eMost likely, this is because the ${layerLib} library script was either not correctly included.\x3cbr\x3e\x3cbr\x3eDevelopers: For help getting this working correctly, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",
 
     'scale': "Měřítko = 1 : ${scaleDenom}",
 
-    // console message
-    'layerAlreadyAdded':
-        "Pokusili jste se přidat vrstvu: ${layerName} do mapy, ale tato vrstva je již v mapě přítomna.",
+    'layerAlreadyAdded': "Pokusili jste se přidat vrstvu: ${layerName} do mapy, ale tato vrstva je již v mapě přítomna.",
 
-    // console message
-    'reprojectDeprecated':
-        "Použil jste volbu 'reproject' " +
-        "ve vrstvě ${layerName}. Tato volba není doporučená: " +
-        "byla zde proto, aby bylo možno zobrazovat data z okomerčních serverů, " + 
-        "ale tato funkce je nyní zajištěna pomocí podpory " +
-        "Spherical Mercator. Více informací naleznete na " +
-        "http://trac.openlayers.org/wiki/SphericalMercator.",
+    'reprojectDeprecated': "Použil jste volbu \'reproject\' ve vrstvě ${layerName}. Tato volba není doporučená: byla zde proto, aby bylo možno zobrazovat data z okomerčních serverů, ale tato funkce je nyní zajištěna pomocí podpory Spherical Mercator. Více informací naleznete na http://trac.openlayers.org/wiki/SphericalMercator.",
 
-    // console message
-    'methodDeprecated':
-        "Tato metodat není doporučená a bude vyjmuta ve verzi 3.0. " +
-        "Prosím, použijte raději ${newMethod}.",
+    'methodDeprecated': "Tato metoda je zavržená a bude ve verzi 3.0 odstraněna. Prosím, použijte raději ${newMethod}.",
 
-    // console message
     'boundsAddError': "Pro přídavnou funkci musíte zadat obě souřadnice x a y.",
 
-    // console message
     'lonlatAddError': "Pro přídavnou funkci musíte zadat obě souřadnice lon a lat.",
 
-    // console message
     'pixelAddError': "Pro přídavnou funkci musíte zadat obě souřadnice x a y.",
 
-    // console message
     'unsupportedGeometryType': "Nepodporovaný typ geometrie: ${geomType}",
 
-    // console message
-    'pagePositionFailed':
-        "OpenLayers.Util.pagePosition selhalo: element s  id ${elemId} je asi umístěn chybně.",
-                    
-    'end': ''
-};
+    'pagePositionFailed': "OpenLayers.Util.pagePosition selhalo: element s  id ${elemId} je asi umístěn chybně."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/da-DK.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/da-DK.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/da-DK.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */
@@ -14,7 +10,7 @@
  */
 OpenLayers.Lang['da-DK'] = {
 
-    'unhandledRequest': "En ikke håndteret forespørgsel returnerede ${statusText}",
+    'unhandledRequest': "En ikke håndteret forespørgsel returnerede ${statusText}",
 
     'permalink': "Permalink",
 
@@ -23,37 +19,37 @@
     'baseLayer': "Baggrundslag",
 
     'sameProjection':
-        "Oversigtskortet fungerer kun når det har samme projektion som hovedkortet",
+        "Oversigtskortet fungerer kun når det har samme projektion som hovedkortet",
 
-    'readNotImplemented': "Læsning er ikke implementeret.",
+    'readNotImplemented': "Læsning er ikke implementeret.",
 
     'writeNotImplemented': "Skrivning er ikke implementeret.",
 
     'noFID': "Kan ikke opdateret en feature (et objekt) der ikke har et FID.",
 
-    'errorLoadingGML': "Fejlede under indlæsning af GML fil ${url}",
+    'errorLoadingGML': "Fejlede under indlæsning af GML fil ${url}",
 
     'browserNotSupported':
-        "Din browser understøtter ikke vektor visning. Følgende vektor visninger understøttes:\n${renderers}",
+        "Din browser understøtter ikke vektor visning. Følgende vektor visninger understøttes:\n${renderers}",
 
-    'componentShouldBe': "addFeatures : komponenten skal være en ${geomType}",
+    'componentShouldBe': "addFeatures : komponenten skal være en ${geomType}",
 
     // console message
     'getFeatureError':
-        "getFeatureFromEvent blev kaldt på et lag uden en visning. Dette betyder som regel at du " +
-        "har destrueret et lag, men ikke de håndteringer der var tilknyttet.",
+        "getFeatureFromEvent blev kaldt på et lag uden en visning. Dette betyder som regel at du " +
+        "har destrueret et lag, men ikke de håndteringer der var tilknyttet.",
 
     // console message
     'minZoomLevelError':
         "Egenskaben minZoomLevel er kun beregnet til brug " +
         "med FixedZoomLevels. At dette WFS lag kontrollerer " +
         "minZoomLevel egenskaben, er et levn fra en tidligere " +
-        "version. Vi kan desværre ikke fjerne dette uden at risikere " +
-        "at ødelægge eksisterende OL baserede programmer der " +
+        "version. Vi kan desværre ikke fjerne dette uden at risikere " +
+        "at ødelægge eksisterende OL baserede programmer der " +
         " benytter denne funktionalitet. " +
-        "Egenskaben bør derfor ikke anvendes, og minZoomLevel " +
+        "Egenskaben bør derfor ikke anvendes, og minZoomLevel " +
         "kontrollen herunder vil blive fjernet i version 3.0. " +
-        "Benyt istedet min/max opløsnings indstillingerne, som " +
+        "Benyt istedet min/max opløsnings indstillingerne, som " +
         "er beskrevet her: " +
         "http://trac.openlayers.org/wiki/SettingZoomLevels",
 
@@ -62,61 +58,61 @@
     'commitFailed': "WFS transaktion: MISLYKKEDES ${response}",
 
     'googleWarning':
-        "Google laget kunne ikke indlæses.<br><br>" +
-        "For at fjerne denne besked, vælg et nyt bagrundskort i " +
-        "lagskifteren i øverste højre hjørne.<br><br>" +
+        "Google laget kunne ikke indlæses.<br><br>" +
+        "For at fjerne denne besked, vælg et nyt bagrundskort i " +
+        "lagskifteren i øverste højre hjørne.<br><br>" +
         "Fejlen skyldes formentlig at Google Maps bibliotekts " +
         "scriptet ikke er inkluderet, eller ikke indeholder den " +
-        "korrkte API nøgle for dit site.<br><br>" +
-        "Udviklere: For hjælp til at få dette til at fungere, " +
+        "korrkte API nøgle for dit site.<br><br>" +
+        "Udviklere: For hjælp til at få dette til at fungere, " +
         "<a href='http://trac.openlayers.org/wiki/Google' " +
         "target='_blank'>klik her</a>",
 
     'getLayerWarning':
-        "${layerType}-laget kunne ikke indlæses.<br><br>" +
-        "For at fjerne denne besked, vælg et nyt bagrundskort i " +
-        "lagskifteren i øverste højre hjørne.<br><br>" +
+        "${layerType}-laget kunne ikke indlæses.<br><br>" +
+        "For at fjerne denne besked, vælg et nyt bagrundskort i " +
+        "lagskifteren i øverste højre hjørne.<br><br>" +
         "Fejlen skyldes formentlig at ${layerLib} bibliotekts " +
         "scriptet ikke er inkluderet.<br><br>" +
-        "Udviklere: For hjælp til at få dette til at fungere, " +
+        "Udviklere: For hjælp til at få dette til at fungere, " +
         "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
         "target='_blank'>klik her</a>",
 
-    'scale': "Målforhold = 1 : ${scaleDenom}",
+    'scale': "MÃ¥lforhold = 1 : ${scaleDenom}",
 
     // console message
     'layerAlreadyAdded':
-        "Du har forsøgt at tilføje laget: ${layerName} til kortet, men det er allerede tilføjet",
+        "Du har forsøgt at tilføje laget: ${layerName} til kortet, men det er allerede tilføjet",
 
     // console message
     'reprojectDeprecated':
-        "Du anvender indstillingen 'reproject' på laget ${layerName}." + 
-        "Denne indstilling bør ikke længere anvendes. Den var beregnet " +
-        "til at vise data ovenpå kommercielle grundkort, men den funktionalitet " +
-        "bør nu opnås ved at anvende Spherical Mercator understøttelsen. " +
-        "Mere information er tilgængelig her: " +
+        "Du anvender indstillingen 'reproject' på laget ${layerName}." + 
+        "Denne indstilling bør ikke længere anvendes. Den var beregnet " +
+        "til at vise data ovenpå kommercielle grundkort, men den funktionalitet " +
+        "bør nu opnås ved at anvende Spherical Mercator understøttelsen. " +
+        "Mere information er tilgængelig her: " +
         "http://trac.openlayers.org/wiki/SphericalMercator.",
 
     // console message
     'methodDeprecated':
-        "Denne funktion bør ikke længere anvendes, og vil blive fjernet i version 3.0. " +
+        "Denne funktion bør ikke længere anvendes, og vil blive fjernet i version 3.0. " +
         "Anvend venligst funktionen ${newMethod} istedet.",
 
     // console message
-    'boundsAddError': "Du skal angive både x og y værdier i kaldet til add funktionen.",
+    'boundsAddError': "Du skal angive både x og y værdier i kaldet til add funktionen.",
 
     // console message
-    'lonlatAddError': "Du skal angive både lon og lat værdier i kaldet til add funktionen.",
+    'lonlatAddError': "Du skal angive både lon og lat værdier i kaldet til add funktionen.",
 
     // console message
-    'pixelAddError': "Du skal angive både x og y værdier i kaldet til add funktionen.",
+    'pixelAddError': "Du skal angive både x og y værdier i kaldet til add funktionen.",
 
     // console message
-    'unsupportedGeometryType': "Geometri typen: ${geomType} er ikke understøttet.",
+    'unsupportedGeometryType': "Geometri typen: ${geomType} er ikke understøttet.",
 
     // console message
     'pagePositionFailed':
-        "OpenLayers.Util.pagePosition fejlede: elementet med id ${elemId} er måske placeret forkert.",
+        "OpenLayers.Util.pagePosition fejlede: elementet med id ${elemId} er måske placeret forkert.",
 
     // console message
     'filterEvaluateNotImplemented': "evaluering er ikke implementeret for denne filter type."

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/de.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/de.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/de.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,18 +1,20 @@
-/* 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. */
+/* Translators (2009 onwards):
+ *  - Grille chompa
+ *  - Nikiwaibel
+ *  - Umherirrender
+ */
 
 /**
- * @requires OpenLayers/Lang/en.js
+ * @requires OpenLayers/Lang.js
  */
 
 /**
  * Namespace: OpenLayers.Lang["de"]
- * Dictionary for German.  Keys for entries are used in calls to
+ * Dictionary for Deutsch.  Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
-OpenLayers.Lang.de = OpenLayers.Util.applyDefaults({
+OpenLayers.Lang["de"] = OpenLayers.Util.applyDefaults({
 
     'unhandledRequest': "Unbehandelte Anfragerückmeldung ${statusText}",
 
@@ -22,8 +24,7 @@
 
     'baseLayer': "Grundkarte",
 
-    'sameProjection':
-        "Die Ãœbersichtskarte funktioniert nur, wenn sie dieselbe Projektion wie die Hauptkarte verwendet",
+    'sameProjection': "Die Ãœbersichtskarte funktioniert nur, wenn sie dieselbe Projektion wie die Hauptkarte verwendet",
 
     'readNotImplemented': "Lesen nicht implementiert.",
 
@@ -33,37 +34,48 @@
 
     'errorLoadingGML': "Fehler beim Laden der GML-Datei ${url}",
 
-    'browserNotSupported':
-        "Ihr Browser unterstützt keine Vektordarstellung. Aktuell unterstützte Renderer:\n${renderers}",
+    'browserNotSupported': "Ihr Browser unterstützt keine Vektordarstellung. Aktuell unterstützte Renderer:\n${renderers}",
 
-    'componentShouldBe': "addFeatures : Komponente sollte vom Typ ${geomType} sein",
+    'componentShouldBe': "addFeatures: Komponente muss vom Typ ${geomType} sein",
 
-    'commitSuccess': "WFS-Transaktion: ERFOLGREICH ${response}",
+    'getFeatureError': "getFeatureFromEvent wurde vom einem Layer ohne Renderer aufgerufen. Dies bedeutet normalerweise, dass ein Layer entfernt wurde, aber nicht Handler, die auf ihn verweisen.",
 
-    'commitFailed': "WFS-Transaktion: FEHLGESCHLAGEN ${response}",
+    'minZoomLevelError': "Die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft ist nur für die Verwendung mit \x3ccode\x3eFixedZoomLevels\x3c/code\x3e-untergeordneten Layers vorgesehen. Das dieser \x3ctt\x3ewfs\x3c/tt\x3e-Layer die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft überprüft ist ein Relikt der Vergangenheit. Wir können diese Überprüfung nicht entfernen, ohne das OL basierende Applikationen nicht mehr funktionieren. Daher markieren wir es als veraltet - die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Überprüfung wird in Version 3.0 entfernt werden. Bitte verwenden Sie stattdessen die Min-/Max-Lösung, wie sie unter http://trac.openlayers.org/wiki/SettingZoomLevels beschrieben ist.",
 
-    'googleWarning':
-        "Der Google-Layer konnte nicht korrekt geladen werden.<br><br>" +
-        "Um diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen " +
-        "Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.<br><br>" +
-        "Sehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der " +
-        "Google-Maps-Bibliothek nicht eingebunden wurde oder keinen gültigen " +
-        "API-Schlüssel für Ihre URL enthält.<br><br>" +
-        "Entwickler: Für Hilfe zum korrekten Einbinden des Google-Layers " +
-        "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>hier klicken</a>",
+    'commitSuccess': "WFS-Transaktion: Erfolgreich ${response}",
 
-    'getLayerWarning':
-        "Der ${layerType}-Layer konnte nicht korrekt geladen werden.<br><br>" +
-        "Um diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen " +
-        "Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.<br><br>" +
-        "Sehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der " +
-        '"${layerLib}"-Bibliothek nicht eingebunden wurde.<br><br>' +
-        "Entwickler: Für Hilfe zum korrekten Einbinden von Layern " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>hier klicken</a>",
+    'commitFailed': "WFS-Transaktion: Fehlgeschlagen ${response}",
 
+    'googleWarning': "Der Google-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der Google-Maps-Bibliothek nicht eingebunden wurde oder keinen gültigen API-Schlüssel für Ihre URL enthält.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden des Google-Layers",
+
+    'getLayerWarning': "Der ${layerType}-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der \'${layerLib}\'-Bibliothek nicht eingebunden wurde.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden von Layern",
+
     'scale': "Maßstab = 1 : ${scaleDenom}",
 
-    'end': ''
-}, OpenLayers.Lang["en"]);
+    'W': "W",
+
+    'E': "O",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Sie versuchen den Layer „${layerName}“ zur Karte hinzuzufügen, er wurde aber bereits hinzugefügt",
+
+    'reprojectDeprecated': "Sie verwenden die „Reproject“-Option des Layers ${layerName}. Diese Option ist veraltet: Sie wurde entwickelt um die Anzeige von Daten auf kommerziellen Basiskarten zu unterstützen, aber diese Funktion sollte jetzt durch Unterstützung der „Spherical Mercator“ erreicht werden. Weitere Informationen sind unter http://trac.openlayers.org/wiki/SphericalMercator verfügbar.",
+
+    'methodDeprecated': "Die Methode ist veraltet und wird in 3.0 entfernt. Bitte verwende stattdessen ${newMethod}.",
+
+    'boundsAddError': "Beide Werte (x und y) müssen der add-Funktion übergeben werden.",
+
+    'lonlatAddError': "Beide Werte (lon und lat) müssen der add-Funktion übergeben werden.",
+
+    'pixelAddError': "Beide Werte (x und y) müssen der add-Funktion übergeben werden.",
+
+    'unsupportedGeometryType': "Nicht unterstützter Geometrie-Typ: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition fehlgeschlagen: Element mit Id ${elemId} möglicherweise falsch platziert.",
+
+    'filterEvaluateNotImplemented': "„evaluate“ ist für diesen Filter-Typ nicht implementiert."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/el.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/el.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/el.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/el.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+/* Translators (2009 onwards):
+ *  - Omnipaedista
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["el"]
+ * Dictionary for Ελληνικά.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["el"] = OpenLayers.Util.applyDefaults({
+
+    'scale': "Κλίμακα ~ 1 : ${scaleDenom}"
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/en-CA.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/en-CA.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/en-CA.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang/en.js
  */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/en.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/en.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/en.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */
@@ -81,6 +77,13 @@
         "target='_blank'>click here</a>",
 
     'scale': "Scale = 1 : ${scaleDenom}",
+    
+    //labels for the graticule control
+    'W': 'W',
+    'E': 'E',
+    'N': 'N',
+    'S': 'S',
+    'graticule': 'Graticule',
 
     // console message
     'layerAlreadyAdded':
@@ -115,9 +118,11 @@
     // console message
     'pagePositionFailed':
         "OpenLayers.Util.pagePosition failed: element with id ${elemId} may be misplaced.",
-                    
-    'end': '',
 
     // console message
-    'filterEvaluateNotImplemented': "evaluate is not implemented for this filter type."
+    'filterEvaluateNotImplemented': "evaluate is not implemented for this filter type.",
+
+    // **** end ****
+    'end': ''
+    
 };

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/es.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/es.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/es.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */
@@ -23,7 +19,7 @@
     'baseLayer': "Capa Base",
 
     'sameProjection':
-        "El mini mapa sólo funciona si está en la misma proyección que el mapa principal",
+        "El mapa de vista general sólo funciona si está en la misma proyección que el mapa principal",
 
     'readNotImplemented': "Lectura no implementada.",
 
@@ -40,14 +36,14 @@
 
     // console message
     'getFeatureError':
-        "getFeatureFromEvent llamado en una capa sin renderizador. Esto normalmente quiere decir que " +
+        "getFeatureFromEvent se ha llamado desde una capa sin renderizador. Esto normalmente quiere decir que " +
         "se ha destruido una capa, pero no el manejador asociado a ella.",
 
     // console message
     'minZoomLevelError':
         "La propiedad minZoomLevel debe sólo utilizarse " +
         "con las capas que tienen FixedZoomLevels. El hecho de que " +
-        "una capa wfs compruebe minZoomLevel is una reliquia del " +
+        "una capa wfs compruebe minZoomLevel es una reliquia del " +
         "pasado. Sin embargo, no podemos eliminarla sin discontinuar " +
         "probablemente las aplicaciones OL que puedan depender de ello. " +
         "Así pues estamos haciéndolo obsoleto --la comprobación " +
@@ -83,6 +79,13 @@
 
     'scale': "Escala = 1 : ${scaleDenom}",
 
+    //labels for the graticule control
+    'W': 'O',
+    'E': 'E',
+    'N': 'N',
+    'S': 'S',
+    'graticule': 'Retícula',
+    
     // console message
     'layerAlreadyAdded':
         "Intentó añadir la capa: ${layerName} al mapa, pero ya había sido añadida previamente",
@@ -90,15 +93,15 @@
     // console message
     'reprojectDeprecated':
         "Está usando la opción 'reproject' en la capa " +
-        "${layerName}. Esta opción está obsoleta: su uso fue diseñado " +
+        "${layerName}. Esta opción es obsoleta: su uso fue diseñado " +
         "para soportar la visualización de datos sobre mapas base comerciales, " + 
-        "pero esa funcionalidad debería conseguirse ahora mediante el soporte " +
+        "pero ahora esa funcionalidad debería conseguirse mediante el soporte " +
         "de la proyección Spherical Mercator. Más información disponible en " +
         "http://trac.openlayers.org/wiki/SphericalMercator.",
 
     // console message
     'methodDeprecated':
-        "Este método está obsoleto y se eliminará en la versión 3.0. " +
+        "Este método es obsoleto y se eliminará en la versión 3.0. " +
         "Por favor utilice el método ${newMethod} en su lugar.",
 
     // console message
@@ -120,6 +123,7 @@
     // console message
     'filterEvaluateNotImplemented': "evaluate no está implementado para este tipo de filtro.",
 
+    // **** end ****
     'end': ''
 
 };

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/fi.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/fi.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/fi.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/fi.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,34 @@
+/* Translators (2009 onwards):
+ *  - Nike
+ *  - Str4nd
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["fi"]
+ * Dictionary for Suomi.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["fi"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "Ikilinkki",
+
+    'overlays': "Kerrokset",
+
+    'baseLayer': "Peruskerros",
+
+    'sameProjection': "Yleiskuvakarttaa voi käyttää vain, kun sillä on sama projektio kuin pääkartalla.",
+
+    'W': "L",
+
+    'E': "I",
+
+    'N': "P",
+
+    'S': "E"
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/fr.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/fr.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/fr.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* Translators (2009 onwards):
+ *  - Damouns
+ *  - IAlex
+ */
 
 /**
  * @requires OpenLayers/Lang.js
@@ -8,11 +9,11 @@
 
 /**
  * Namespace: OpenLayers.Lang["fr"]
- * Dictionary for French.  Keys for entries are used in calls to
+ * Dictionary for Français.  Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
-OpenLayers.Lang.fr = {
+OpenLayers.Lang["fr"] = OpenLayers.Util.applyDefaults({
 
     'unhandledRequest': "Requête non gérée, retournant ${statusText}",
 
@@ -22,8 +23,7 @@
 
     'baseLayer': "Calque de base",
 
-    'sameProjection':
-        "La carte de situation ne fonctionne que lorsque sa projection est la même que celle de la carte principale",
+    'sameProjection': "La carte de situation ne fonctionne que lorsque sa projection est la même que celle de la carte principale",
 
     'readNotImplemented': "Lecture non implémentée.",
 
@@ -33,89 +33,48 @@
 
     'errorLoadingGML': "Erreur au chargement du fichier GML ${url}",
 
-    'browserNotSupported':
-        "Votre navigateur ne supporte pas le rendu vectoriel. Les renderers actuellement supportés sont : \n${renderers}",
+    'browserNotSupported': "Votre navigateur ne supporte pas le rendu vectoriel. Les renderers actuellement supportés sont : \n${renderers}",
 
     'componentShouldBe': "addFeatures : le composant devrait être de type ${geomType}",
 
-    // console message
-    'getFeatureError':
-        "getFeatureFromEvent a été appelé sur un calque sans renderer. Cela signifie généralement que vous " +
-        "avez détruit cette couche, mais que vous avez conservé un handler qui lui était associé.",
+    'getFeatureError': "getFeatureFromEvent a été appelé sur un calque sans renderer. Cela signifie généralement que vous avez détruit cette couche, mais que vous avez conservé un handler qui lui était associé.",
 
-    // console message
-    'minZoomLevelError':
-        "La propriété minZoomLevel doit seulement être utilisée " +
-        "pour des couches FixedZoomLevels-descendent. Le fait que " +
-        "cette couche WFS vérifie la présence de minZoomLevel " +
-        "est une relique du passé. Nous ne pouvons toutefois la " +
-        "supprimer sans casser des applications qui pourraient en dépendre." +
-        " C'est pourquoi nous la déprécions -- la vérification du minZoomLevel " +
-        "sera supprimée en version 3.0. A la place, merci d'utiliser " +
-        "les paramètres de résolutions min/max tel que décrit sur : " +
-        "http://trac.openlayers.org/wiki/SettingZoomLevels",
+    'minZoomLevelError': "La propriété minZoomLevel doit seulement être utilisée pour des couches FixedZoomLevels-descendent. Le fait que cette couche WFS vérifie la présence de minZoomLevel est une relique du passé. Nous ne pouvons toutefois la supprimer sans casser des applications qui pourraient en dépendre. C\'est pourquoi nous la déprécions -- la vérification du minZoomLevel sera supprimée en version 3.0. A la place, merci d\'utiliser les paramètres de résolutions min/max tel que décrit sur : http://trac.openlayers.org/wiki/SettingZoomLevels",
 
     'commitSuccess': "Transaction WFS : SUCCES ${response}",
 
     'commitFailed': "Transaction WFS : ECHEC ${response}",
 
-    'googleWarning':
-        "La couche Google n'a pas été en mesure de se charger correctement.<br><br>" +
-        "Pour supprimer ce message, choisissez une nouvelle BaseLayer " +
-        "dans le sélecteur de couche en haut à droite.<br><br>" +
-        "Cela est possiblement causé par la non-inclusion de la " +
-        "librairie Google Maps, ou alors parce que la clé de l'API " +
-        "ne correspond pas à votre site.<br><br>" +
-        "Développeurs : pour savoir comment corriger ceci, " +
-        "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>cliquez ici</a>",
+    'googleWarning': "La couche Google n\'a pas été en mesure de se charger correctement.\x3cbr\x3e\x3cbr\x3ePour supprimer ce message, choisissez une nouvelle BaseLayer dans le sélecteur de couche en haut à droite.\x3cbr\x3e\x3cbr\x3eCela est possiblement causé par la non-inclusion de la librairie Google Maps, ou alors parce que la clé de l\'API ne correspond pas à votre site.\x3cbr\x3e\x3cbr\x3eDéveloppeurs : pour savoir comment corriger ceci, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ecliquez ici\x3c/a\x3e",
 
-    'getLayerWarning':
-        "La couche ${layerType} n'est pas en mesure de se charger correctement.<br><br>" +
-        "Pour supprimer ce message, choisissez une nouvelle BaseLayer " +
-        "dans le sélecteur de couche en haut à droite.<br><br>" +
-        "Cela est possiblement causé par la non-inclusion de la " +
-        "librairie ${layerLib}.<br><br>" +
-        "Développeurs : pour savoir comment corriger ceci, " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>cliquez ici</a>",
+    'getLayerWarning': "La couche ${layerType} n\'est pas en mesure de se charger correctement.\x3cbr\x3e\x3cbr\x3ePour supprimer ce message, choisissez une nouvelle BaseLayer dans le sélecteur de couche en haut à droite.\x3cbr\x3e\x3cbr\x3eCela est possiblement causé par la non-inclusion de la librairie ${layerLib}.\x3cbr\x3e\x3cbr\x3eDéveloppeurs : pour savoir comment corriger ceci, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ecliquez ici\x3c/a\x3e",
 
     'scale': "Echelle ~ 1 : ${scaleDenom}",
 
-    // console message
-    'layerAlreadyAdded':
-        "Vous avez essayé d'ajouter à la carte le calque : ${layerName}, mais il est déjà présent",
+    'W': "O",
 
-    // console message
-    'reprojectDeprecated':
-        "Vous utilisez l'option 'reproject' " +
-        "sur la couche ${layerName}. Cette option est dépréciée : " +
-        "Son usage permettait d'afficher des données au dessus de couches raster commerciales." + 
-        "Cette fonctionalité est maintenant supportée en utilisant le support de la projection " +
-        "Mercator Sphérique. Plus d'information est disponible sur " +
-        "http://trac.openlayers.org/wiki/SphericalMercator.",
+    'E': "E",
 
-    // console message
-    'methodDeprecated':
-        "Cette méthode est dépréciée, et sera supprimée à la version 3.0. " +
-        "Merci d'utiliser ${newMethod} à la place.",
+    'N': "N",
 
-    // console message
+    'S': "S",
+
+    'layerAlreadyAdded': "Vous avez essayé d\'ajouter à la carte le calque : ${layerName}, mais il est déjà présent",
+
+    'reprojectDeprecated': "Vous utilisez l\'option \'reproject\' sur la couche ${layerName}. Cette option est dépréciée : Son usage permettait d\'afficher des données au dessus de couches raster commerciales.Cette fonctionalité est maintenant supportée en utilisant le support de la projection Mercator Sphérique. Plus d\'information est disponible sur http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Cette méthode est dépréciée, et sera supprimée à la version 3.0. Merci d\'utiliser ${newMethod} à la place.",
+
     'boundsAddError': "Vous devez passer les deux valeurs x et y à la fonction add.",
 
-    // console message
     'lonlatAddError': "Vous devez passer les deux valeurs lon et lat à la fonction add.",
 
-    // console message
     'pixelAddError': "Vous devez passer les deux valeurs x et y à la fonction add.",
 
-    // console message
     'unsupportedGeometryType': "Type de géométrie non supporté : ${geomType}",
 
-    // console message
-    'pagePositionFailed':
-        "OpenLayers.Util.pagePosition a échoué: l'élément d'id ${elemId} pourrait être mal positionné.",
-    
-    'end': ''
+    'pagePositionFailed': "OpenLayers.Util.pagePosition a échoué: l\'élément d\'id ${elemId} pourrait être mal positionné.",
 
-};
+    'filterEvaluateNotImplemented': "évaluer n\'a pas encore été implémenté pour ce type de filtre."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/fur.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/fur.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/fur.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/fur.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,35 @@
+/* Translators (2009 onwards):
+ *  - Klenje
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["fur"]
+ * Dictionary for Furlan.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["fur"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "Leam Permanent",
+
+    'overlays': "Livei parsore",
+
+    'baseLayer': "Livel di base",
+
+    'browserNotSupported': "Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",
+
+    'scale': "Scjale = 1 : ${scaleDenom}",
+
+    'W': "O",
+
+    'E': "E",
+
+    'N': "N",
+
+    'S': "S"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/gl.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/gl.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/gl.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/gl.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Toliño
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["gl"]
+ * Dictionary for Galego.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["gl"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Solicitude non xerada; a resposta foi: ${statusText}",
+
+    'permalink': "Ligazón permanente",
+
+    'overlays': "Capas superpostas",
+
+    'baseLayer': "Capa base",
+
+    'sameProjection': "A vista xeral do mapa só funciona cando está na mesma proxección có mapa principal",
+
+    'readNotImplemented': "Lectura non implementada.",
+
+    'writeNotImplemented': "Escritura non implementada.",
+
+    'noFID': "Non se pode actualizar a funcionalidade para a que non hai FID.",
+
+    'errorLoadingGML': "Erro ao cargar o ficheiro GML ${url}",
+
+    'browserNotSupported': "O seu navegador non soporta a renderización de vectores. Os renderizadores soportados actualmente son:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: o compoñente debera ser de tipo ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent ten sido chamado a unha capa sen renderizador. Isto normalmente significa que destruíu unha capa, mais non o executador que está asociado con ela.",
+
+    'minZoomLevelError': "A propiedade minZoomLevel é só para uso conxuntamente coas capas FixedZoomLevels-descendent. O feito de que esa capa wfs verifique o minZoomLevel é unha reliquia do pasado. Non podemos, con todo, eliminala sen a posibilidade de non romper as aplicacións baseadas en OL que poidan depender dela. Por iso a estamos deixando obsoleta (a comprobación minZoomLevel de embaixo será eliminada na versión 3.0). Por favor, no canto diso use o axuste de resolución mín/máx tal e como está descrito aquí: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Transacción WFS: ÉXITO ${response}",
+
+    'commitFailed': "Transacción WFS: FALLIDA ${response}",
+
+    'googleWarning': "A capa do Google non puido cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría do Google Maps ou ben non foi incluída ou ben non contén a clave API correcta para o seu sitio.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",
+
+    'getLayerWarning': "A capa ${layerType} foi incapaz de cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría ${layerLib} non foi ben incluída.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",
+
+    'scale': "Escala = 1 : ${scaleDenom}",
+
+    'W': "O",
+
+    'E': "L",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Intentou engadir a capa: ${layerName} ao mapa, pero xa fora engadida",
+
+    'reprojectDeprecated': "Está usando a opción \"reproject\" na capa ${layerName}. Esta opción está obsoleta: o seu uso foi deseñado para a visualización de datos sobre mapas base comerciais, pero esta funcionalidade debera agora ser obtida utilizando a proxección Spherical Mercator. Hai dispoñible máis información en http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Este método está obsoleto e será eliminado na versión 3.0. Por favor, no canto deste use ${newMethod}.",
+
+    'boundsAddError': "Debe achegar os valores x e y á función add.",
+
+    'lonlatAddError': "Debe achegar tanto o valor lon coma o lat á función add.",
+
+    'pixelAddError': "Debe achegar os valores x e y á función add.",
+
+    'unsupportedGeometryType': "Tipo xeométrico non soportado: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition fallou: o elemento con id ${elemId} pode non estar na súa posición.",
+
+    'filterEvaluateNotImplemented': "avaliar non está implementado para este tipo de filtro."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/gsw.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/gsw.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/gsw.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/gsw.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Als-Holder
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["gsw"]
+ * Dictionary for Alemannisch.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["gsw"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Nit behandleti Aafrogsruckmäldig ${statusText}",
+
+    'permalink': "Permalink",
+
+    'overlays': "Iberlagerige",
+
+    'baseLayer': "Grundcharte",
+
+    'sameProjection': "D Ibersichts-Charte funktioniert nume, wänn si di glych Projäktion brucht wie d Hauptcharte",
+
+    'readNotImplemented': "Läse nit implementiert.",
+
+    'writeNotImplemented': "Schrybe nit implementiert.",
+
+    'noFID': "E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",
+
+    'errorLoadingGML': "Fähler bim Lade vu dr GML-Datei ${url}",
+
+    'browserNotSupported': "Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",
+
+    'componentShouldBe': "addFeatures : Komponänt sott dr Typ ${geomType} syy",
+
+    'getFeatureError': "getFeatureFromEvent isch uf eme Layer ohni Renderer ufgruefe wore. Des heisst normalerwys, ass Du e Layer kaputt gmacht hesch, aber nit dr Handler, wu derzue ghert.",
+
+    'minZoomLevelError': "D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge.  Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS-Transaktion: ERFOLGRYCH ${response}",
+
+    'commitFailed': "WFS-Transaktion: FÄHLGSCHLAA ${response}",
+
+    'googleWarning': "Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",
+
+    'getLayerWarning': "Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",
+
+    'scale': "Maßstab = 1 : ${scaleDenom}",
+
+    'W': "W",
+
+    'E': "O",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Du hesch versuecht dää Layer in d Charte yyzfiege: ${layerName}, aber är isch schoi yygfiegt",
+
+    'reprojectDeprecated': "Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go   Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}.",
+
+    'boundsAddError': "Du muesch e x-Wärt un e y-Wärt yygee bi dr Zuefieg-Funktion",
+
+    'lonlatAddError': "Du meusch e Lengi- un e Breiti-Grad yygee bi dr Zuefieg-Funktion.",
+
+    'pixelAddError': "Du muesch x- un y-Wärt aagee bi dr Zuefieg-Funktion.",
+
+    'unsupportedGeometryType': "Nit unterstitze Geometrii-Typ: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition fählgschlaa: Elemänt mit ID ${elemId} isch villicht falsch gsetzt.",
+
+    'filterEvaluateNotImplemented': "evaluiere isch nit implemäntiert in däm Filtertyp."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/hr.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/hr.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/hr.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/hr.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,61 @@
+/* Translators (2009 onwards):
+ *  - Mvrban
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["hr"]
+ * Dictionary for Hrvatski.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["hr"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Nepodržani zahtjev ${statusText}",
+
+    'permalink': "Permalink",
+
+    'overlays': "Overlays",
+
+    'baseLayer': "Osnovna karta",
+
+    'sameProjection': "Pregledna karta radi jedino kao je u istoj projekciji kao i glava karta",
+
+    'readNotImplemented': "ÄŒitanje nije implementirano.",
+
+    'writeNotImplemented': "Pisanje nije implementirano.",
+
+    'noFID': "Ne mogu ažurirati značajku za koju ne postoji FID.",
+
+    'errorLoadingGML': "Greška u učitavanju GML datoteke ${url}",
+
+    'browserNotSupported': "Vaš preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",
+
+    'componentShouldBe': "addFeatures : komponenta bi trebala biti ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent je pozvao Layer bez renderera. Ovo obično znači da ste uništiili Layer, a ne neki Handler koji je povezan s njim.",
+
+    'commitSuccess': "WFS Transakcija: USPJEÅ NA ${response}",
+
+    'commitFailed': "WFS Transakcija: NEUSPJEÅ NA ${response}",
+
+    'scale': "Mjerilo = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Pokušali ste dodati layer:  ${layerName} na kartu, ali je već dodan",
+
+    'methodDeprecated': "Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}.",
+
+    'boundsAddError': "Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",
+
+    'lonlatAddError': "Morate dati obje vrijednosti , (lon i lat) da bi dodali funkciju.",
+
+    'pixelAddError': "Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",
+
+    'unsupportedGeometryType': "Nepodržani tip geometrije: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition nije uspjelo: element sa id ${elemId} može biti krivo smješten."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/hsb.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/hsb.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/hsb.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/hsb.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Michawiki
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["hsb"]
+ * Dictionary for Hornjoserbsce.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["hsb"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Wotmołwa njewobdźěłaneho naprašowanja ${statusText}",
+
+    'permalink': "Trajny wotkaz",
+
+    'overlays': "Naworštowanja",
+
+    'baseLayer': "Zakładna runina",
+
+    'sameProjection': "Přehladowa karta jenož funguje, hdyž je w samsnej projekciji kaž hłowna karta",
+
+    'readNotImplemented': "ÄŒitanje njeimplementowane.",
+
+    'writeNotImplemented': "Pisanje njeimplementowane.",
+
+    'noFID': "Funkcija, za kotruž FID njeje, njeda so aktualizować.",
+
+    'errorLoadingGML': "Zmylk při začitowanju dataje ${url}",
+
+    'browserNotSupported': "Twój wobhladowak wektorowe rysowanje njepodpěruje. Tuchwilu podpěrowane rysowaki su:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: komponenta měła ${geomType} być",
+
+    'getFeatureError': "getFeatureFromEvent bu na woršće bjez rysowak zawołany. To zwjetša woznamjenja, zo sy worštu zničił, ale nic wobdźěłak, kotryž je z njej zwjazany.",
+
+    'minZoomLevelError': "Kajkosć minZoomLevel je jenož za wužiwanje z worštami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta woršta wfs za minZoomLevel přepruwuje, je relikt zańdźenosće. Njemóžemy wšak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazěruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- přepruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. Prošu wužij město toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS-Transakcija: WUSPĚŠNA ${response}",
+
+    'commitFailed': "WFS-Transakcija: NJEPORADŹENA ${response}",
+
+    'googleWarning': "Woršta Google njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapřijaty pak njewobsahuje korektny kluč API za twoje sydło.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",
+
+    'getLayerWarning': "Woršta ${layerType} njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapřijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",
+
+    'scale': "Měritko = 1 : ${scaleDenom}",
+
+    'W': "Z",
+
+    'E': "W",
+
+    'N': "S",
+
+    'S': "J",
+
+    'layerAlreadyAdded': "Sy spytał runinu ${layerName} karće dodać, ale je so hižo dodała",
+
+    'reprojectDeprecated': "Wužiwaš opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bě myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpěrało, ale funkcionalnosć měła so nětko z pomocu Sperical Mercator docpěć. Dalše informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",
+
+    'methodDeprecated': "Tuta metoda je so njeschwaliła a budźe so w 3.0 wotstronjeć. Prošu wužij ${newMethod} město toho.",
+
+    'boundsAddError': "Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",
+
+    'lonlatAddError': "Dyrbiš hódnotu lon kaž tež lat funkciji \"add\" přepodać.",
+
+    'pixelAddError': "Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",
+
+    'unsupportedGeometryType': "Njepodpěrowany geometrijowy typ: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition je so njeporadźił: element z id ${elemId} bu snano wopak zaměstnjeny.",
+
+    'filterEvaluateNotImplemented': "wuhódnoćenje njeje za tutón filtrowy typ implementowany."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/hu.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/hu.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/hu.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/hu.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+/* Translators (2009 onwards):
+ *  - City-busz
+ *  - Glanthor Reviol
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["hu"]
+ * Dictionary for Magyar.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["hu"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Nem kezelt kérés visszatérése ${statusText}",
+
+    'permalink': "Permalink",
+
+    'overlays': "Rávetítések",
+
+    'baseLayer': "Alapréteg",
+
+    'sameProjection': "Az áttekintő térkép csak abban az esetben működik, ha ugyanazon a vetületen van, mint a fő térkép.",
+
+    'readNotImplemented': "Olvasás nincs végrehajtva.",
+
+    'writeNotImplemented': "Írás nincs végrehajtva.",
+
+    'noFID': "Nem frissíthető olyan jellemző, amely nem rendelkezik FID-del.",
+
+    'errorLoadingGML': "Hiba GML-fájl betöltésekor ${url}",
+
+    'browserNotSupported': "A böngészője nem támogatja a vektoros renderelést. A jelenleg támogatott renderelők:\n${renderers}",
+
+    'componentShouldBe': "addFeatures : az összetevőnek ilyen típusúnak kell lennie: ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent réteget hívott meg renderelő nélkül. Ez rendszerint azt jelenti, hogy megsemmisített egy fóliát, de néhány ahhoz társított kezelőt nem.",
+
+    'minZoomLevelError': "A minZoomLevel tulajdonságot csak a következővel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölőnégyzetei már a múlté. Mi azonban nem távolíthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettől függő OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenítjük -- a minZoomLevel az alul levő jelölőnégyzet a 3.0-s verzióból el lesz távolítva. Kérjük, helyette használja a  min/max felbontás beállítást, amelyről az alábbi helyen talál leírást: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS tranzakció: SIKERES ${response}",
+
+    'commitFailed': "WFS tranzakció: SIKERTELEN ${response}",
+
+    'googleWarning': "A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelő API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",
+
+    'getLayerWarning': "A(z) ${layerType} fólia nem töltődött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",
+
+    'scale': "Lépték = 1 : ${scaleDenom}",
+
+    'W': "Ny",
+
+    'E': "K",
+
+    'N': "É",
+
+    'S': "D",
+
+    'layerAlreadyAdded': "Megpróbálta hozzáadni a(z) ${layerName} fóliát a térképhez, de az már hozzá van adva",
+
+    'reprojectDeprecated': "Ön a \'reproject\' beállítást használja a(z) ${layerName} fólián. Ez a beállítás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenítésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhető el. További információ az alábbi helyen érhető el: http://trac.openlayers.org/wiki/SphericalMercator",
+
+    'methodDeprecated': "Ez a módszer érvénytelenítve lett és a 3.0-s verzióból el lesz távolítva. Használja a(z) ${newMethod} módszert helyette.",
+
+    'boundsAddError': "Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",
+
+    'lonlatAddError': "A hossz. és szél. értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",
+
+    'pixelAddError': "Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",
+
+    'unsupportedGeometryType': "Nem támogatott geometriatípus: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition sikertelen: lehetséges, hogy a(z) ${elemId} azonosítójú elem téves helyre került.",
+
+    'filterEvaluateNotImplemented': "ennél a szűrőtípusnál kiértékelés nem hajtódik végre."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ia.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/ia.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ia.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ia.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - McDutchie
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["ia"]
+ * Dictionary for Interlingua.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["ia"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Le responsa a un requesta non esseva maneate: ${statusText}",
+
+    'permalink': "Permaligamine",
+
+    'overlays': "Superpositiones",
+
+    'baseLayer': "Strato de base",
+
+    'sameProjection': "Le mini-carta functiona solmente si illo es in le mesme projection que le carta principal",
+
+    'readNotImplemented': "Lectura non implementate.",
+
+    'writeNotImplemented': "Scriptura non implementate.",
+
+    'noFID': "Non pote actualisar un elemento sin FID.",
+
+    'errorLoadingGML': "Error al cargamento del file GML ${url}",
+
+    'browserNotSupported': "Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: le componente debe esser del typo ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent ha essite appellate in un strato sin renditor. Isto significa generalmente que tu ha destruite un strato, ma lassava un gestor associate con illo.",
+
+    'minZoomLevelError': "Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Transaction WFS: SUCCESSO ${response}",
+
+    'commitFailed': "Transaction WFS: FALLEVA ${response}",
+
+    'googleWarning': "Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",
+
+    'getLayerWarning': "Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",
+
+    'scale': "Scala = 1 : ${scaleDenom}",
+
+    'W': "W",
+
+    'E': "E",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Tu tentava adder le strato: ${layerName} al carta, ma illo es ja presente",
+
+    'reprojectDeprecated': "Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco.",
+
+    'boundsAddError': "Tu debe passar le duo valores x e y al function add.",
+
+    'lonlatAddError': "Tu debe passar le duo valores lon e lat al function add.",
+
+    'pixelAddError': "Tu debe passar le duo valores x e y al function add.",
+
+    'unsupportedGeometryType': "Typo de geometria non supportate: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition falleva: le elemento con id ${elemId} pote esser mal placiate.",
+
+    'filterEvaluateNotImplemented': "\"evaluate\" non es implementate pro iste typo de filtro."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/id.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/id.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/id.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/id.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+/* Translators (2009 onwards):
+ *  - Irwangatot
+ *  - IvanLanin
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["id"]
+ * Dictionary for Bahasa Indonesia.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["id"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Permintaan yang tak tertangani menghasilkan ${statusText}",
+
+    'permalink': "Pranala permanen",
+
+    'overlays': "Hamparan",
+
+    'baseLayer': "Lapisan Dasar",
+
+    'sameProjection': "Peta tinjauan hanya bekerja bila dalam proyeksi yang sama dengan peta utama",
+
+    'readNotImplemented': "Membaca tidak diterapkan.",
+
+    'writeNotImplemented': "Menyimpan tidak diterapkan.",
+
+    'noFID': "Tidak dapat memperbarui fitur yang tidak memiliki FID.",
+
+    'errorLoadingGML': "Kesalahan dalam memuat berkas GML ${url}",
+
+    'browserNotSupported': "Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",
+
+    'componentShouldBe': "addFeatures : komponen harus berupa ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent diterapkan pada lapisan tanpa penggambar. Ini biasanya berarti Anda menghapus sebuah lapisan, tetapi tidak menghapus penangan yang terkait dengannya.",
+
+    'minZoomLevelError': "Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS Transaksi: BERHASIL ${respon}",
+
+    'commitFailed': "WFS Transaksi: GAGAL ${respon}",
+
+    'googleWarning': "Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",
+
+    'getLayerWarning': "Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",
+
+    'scale': "Sekala = 1 : ${scaleDenom}",
+
+    'W': "B",
+
+    'E': "T",
+
+    'N': "U",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Anda mencoba menambahkan lapisan: ${layerName} ke dalam peta, tapi lapisan itu telah ditambahkan",
+
+    'reprojectDeprecated': "Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}.",
+
+    'boundsAddError': "Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",
+
+    'lonlatAddError': "Anda harus memberikan kedua nilai lon dan lat ke fungsi penambah.",
+
+    'pixelAddError': "Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",
+
+    'unsupportedGeometryType': "Tipe geometri tak didukung: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition gagal: elemen dengan id ${elemId} mungkin salah tempat.",
+
+    'filterEvaluateNotImplemented': "evaluasi tidak tersedia untuk tipe filter ini."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/io.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/io.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/io.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/io.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+/* Translators (2009 onwards):
+ *  - Malafaya
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["io"]
+ * Dictionary for Ido.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["io"] = OpenLayers.Util.applyDefaults({
+
+    'scale': "Skalo = 1 : ${scaleDenom}"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/is.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/is.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/is.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/is.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,37 @@
+/* Translators (2009 onwards):
+ *  - Ævar Arnfjörð Bjarmason
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["is"]
+ * Dictionary for Íslenska.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["is"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "Varanlegur tengill",
+
+    'overlays': "Þekjur",
+
+    'baseLayer': "Grunnlag",
+
+    'sameProjection': "Yfirlitskortið virkar aðeins ef það er í sömu vörpun og aðalkortið",
+
+    'readNotImplemented': "Skrifun er óútfærð.",
+
+    'writeNotImplemented': "Lestur er óútfærður.",
+
+    'errorLoadingGML': "Villa kom upp við að hlaða inn GML skránni ${url}",
+
+    'scale': "Skali = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Þú reyndir að bæta laginu ${layerName} á kortið en það er þegar búið að bæta því við",
+
+    'methodDeprecated': "Þetta fall hefur verið úrelt og verður fjarlægt í 3.0. Notaðu ${newMethod} í staðin."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/it.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/it.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/it.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ja.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/ja.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ja.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ja.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+/* Translators (2009 onwards):
+ *  - Fryed-peach
+ *  - Mage Whopper
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["ja"]
+ * Dictionary for 日本語.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["ja"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "未処理の要求は ${statusText} を返します",
+
+    'permalink': "パーマリンク",
+
+    'overlays': "オーバーレイ",
+
+    'baseLayer': "基底レイヤー",
+
+    'sameProjection': "概観地図はメインの地図と同じ投影法をとる場合のみ機能します",
+
+    'readNotImplemented': "読み込みは実装されていません。",
+
+    'writeNotImplemented': "書き込みは実装されていません。",
+
+    'noFID': "FID のない地物は更新できません。",
+
+    'errorLoadingGML': "GML ファイル ${url} の読み込みエラー",
+
+    'browserNotSupported': "あなたのブラウザはベクターグラフィックスの描写に対応していません。現時点で対応しているソフトウェアは以下のものです。\n${renderers}",
+
+    'componentShouldBe': "addFeatures: 要素は ${geomType} であるべきです",
+
+    'getFeatureError': "getFeatureFromEvent がレンダラーのないレイヤーから呼ばれました。通常、これはあなたがレイヤーを、それに関連づけられたいくつかのハンドラを除いて、破壊してしまったことを意味します。",
+
+    'minZoomLevelError': "minZoomLevel プロパティは FixedZoomLevels を継承するレイヤーでの使用のみを想定しています。この minZoomLevel に対する WFS レイヤーの検査は歴史的なものです。しかしながら、この検査を除去するとそれに依存する OpenLayers ベースのアプリケーションを破壊してしまう可能性があります。よって廃止が予定されており、この minZoomLevel 検査はバージョン3.0で除去されます。代わりに、http://trac.openlayers.org/wiki/SettingZoomLevels で解説されている、最小および最大解像度設定を使用してください。",
+
+    'commitSuccess': "WFS トランザクション: 成功 ${response}",
+
+    'commitFailed': "WFS トランザクション: 失敗 ${response}",
+
+    'googleWarning': "Google レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは Google マップ用ライブラリのスクリプトが組み込まれていないか、あなたのサイトに対応する正しい API キーが設定されていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",
+
+    'getLayerWarning': "${layerType} レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは ${layerLib} ライブラリのスクリプトが正しく組み込まれていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",
+
+    'scale': "縮尺 = 1 : ${scaleDenom}",
+
+    'W': "西",
+
+    'E': "東",
+
+    'N': "北",
+
+    'S': "南",
+
+    'layerAlreadyAdded': "あなたは「${layerName}」を地図に追加しようと試みましたが、そのレイヤーは既に追加されています",
+
+    'reprojectDeprecated': "あなたは「${layerName}」レイヤーで reproject オプションを使っています。このオプションは商用の基底地図上に情報を表示する目的で設計されましたが、現在ではその機能は Spherical Mercator サポートを利用して実現されており、このオプションの使用は非推奨です。追加の情報は http://trac.openlayers.org/wiki/SphericalMercator で入手できます。",
+
+    'methodDeprecated': "このメソッドは廃止が予定されており、バージョン3.0で除去されます。代わりに ${newMethod} を使用してください。",
+
+    'boundsAddError': "x と y 両方の値を add 関数に渡さなければなりません。",
+
+    'lonlatAddError': "lon と lat 両方の値を add 関数に渡さなければなりません。",
+
+    'pixelAddError': "x と y の値両方を add 関数に渡さなければなりません。",
+
+    'unsupportedGeometryType': "未対応の形状型: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition が失敗しました: id ${elemId} をもつ要素が誤った位置にある可能性があります。",
+
+    'filterEvaluateNotImplemented': "このフィルター型について evaluate は実装されていません。"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/km.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/km.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/km.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/km.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,25 @@
+/* Translators (2009 onwards):
+ *  - វ័ណថារិទ្ធ
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["km"]
+ * Dictionary for ភាសាខ្មែរ.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["km"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "តំណភ្ជាប់អចិន្ត្រៃយ៍",
+
+    'baseLayer': "ស្រទាប់បាត​",
+
+    'errorLoadingGML': "កំហុសកំឡុងពេលផ្ទុកឯកសារ GML ${url}",
+
+    'scale': "មាត្រដ្ឋាន = ១ ៖ ${scaleDenom}"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ksh.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/ksh.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ksh.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ksh.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Purodha
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["ksh"]
+ * Dictionary for Ripoarisch.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["ksh"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Met dä Antwoot op en Aanfrooch ham_mer nix aanjefange: ${statusText}",
+
+    'permalink': "Lengk op Duuer",
+
+    'overlays': "Drövver jelaat",
+
+    'baseLayer': "Jrund-Nivoh",
+
+    'sameProjection': "De Övverseeschs_Kaat deiht et bloß, wann se de sälve Projäxjuhn bruche deiht, wi de Houp_Kaat",
+
+    'readNotImplemented': "„\x3ccode lang=\"en\"\x3eread\x3c/code\x3e“ is em Projramm nit fürjesinn.",
+
+    'writeNotImplemented': "„\x3ccode lang=\"en\"\x3ewrite\x3c/code\x3e“ is em Projramm nit fürjesinn.",
+
+    'noFID': "En Saach, woh kein \x3ci lang=\"en\"\x3eFID\x3c/i\x3e för doh es, löht sesch nit ändere.",
+
+    'errorLoadingGML': "Fähler beim \x3ci lang=\"en\"\x3eGML\x3c/i\x3e-Datei-Laade vun \x3ccode\x3e${url}\x3c/code\x3e",
+
+    'browserNotSupported': "Dinge Brauser kann kein Väktore ußjävve. De Zoote Ußjaabe, di em Momang jon, sen:\n${renderers}",
+
+    'componentShouldBe': "\x3ccode lang=\"en\"\x3eaddFeatures\x3c/code\x3e: dä Aandeil sullt vun dä Zoot „\x3ccode lang=\"en\"\x3e${geomType}\x3c/code\x3e“ sin.",
+
+    'getFeatureError': "\x3ccode lang=\"en\"\x3egetFeatureFromEvent\x3c/code\x3e es vun enem Nivoh opjeroofe woode, woh et kei Projramm zom Ußjävve jit. Dat bedügg för jewöhnlesch, dat De e Nivoh kapott jemaat häs, ävver nit e Projramm för domet ömzejonn, wat domet verbonge es.",
+
+    'minZoomLevelError': "De Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ es bloß doför jedaach, dat mer se met dä Nivvohß bruch, di vun \x3ccode lang=\"en\"\x3eFixedZoomLevels\x3c/code\x3e affhange don. Dat dat \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Nivvoh övverhoup de Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ pröhfe deiht, es noch övveresch vun fröhjer. Mer künne dat ävver jez nit fott lohße, oohne dat mer Jevaa loufe, dat Aanwendunge vun OpenLayers nit mieh loufe, di sesch doh velleijsch noch drop am verlohße sin. Dröm sare mer, dat mer et nit mieh han welle, un de „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“-Eijeschaff weed hee vun de Version 3.0 af nit mieh jeprööf wäde. Nemm doför de Enstellung för de hühßte un de kleinßte Oplöhsung, esu wi et en http://trac.openlayers.org/wiki/SettingZoomLevels opjeschrevve es.",
+
+    'commitSuccess': "Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es joot jeloufe: ${response}",
+
+    'commitFailed': "Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es scheif jejange: ${response}",
+
+    'googleWarning': "Dat Nivvoh \x3ccode lang=\"en\"\x3eGoogle\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhke, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat wiel dat \x3ci lang=\"en\"\x3eGoogle-Maps\x3c/i\x3e-Skrepp entweeder nit reschtesch enjebonge wood, udder nit dä reschtejje \x3ci lang=\"en\"\x3eAPI\x3c/i\x3e-Schlößel för Ding Web-ßait scheke deiht.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/Google\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",
+
+    'getLayerWarning': "Dat Nivvoh \x3ccode\x3e${layerType}\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhkre, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat, wiel dat Skrepp \x3ccode\x3e${layerLib}\x3c/code\x3e nit reschtesch enjebonge wood.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_Et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/${layerLib}\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",
+
+    'scale': "Mohßshtaab = 1 : ${scaleDenom}",
+
+    'W': "W",
+
+    'E': "O",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Do häß versöhk, dat Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e en di Kaat eren ze bränge, et wohr ävver ald do dren.",
+
+    'reprojectDeprecated': "Do bruchs de Ußwahl \x3ccode\x3ereproject\x3c/code\x3e op däm Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e. Di Ußwahl es nit mieh jähn jesinn. Se wohr doför jedaach, öm Date op jeschääfsmäßesch eruß jejovve Kaate bovve drop ze moole, wat ävver enzwesche besser met dä Öngershtözung för de ßfääresche Mäkaator Beldscher jeiht. Doh kanns De mieh drövver fenge op dä Sigg: http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Hee di Metood es nim_mih aktoäll un et weed se en dä Version 3.0 nit mieh jävve. Nemm \x3ccode\x3e${newMethod}\x3c/code\x3e doföör.",
+
+    'boundsAddError': "Do moß beeds vun de \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e Wääte aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",
+
+    'lonlatAddError': "Do moß beeds \x3ccode\x3elon\x3c/code\x3e un \x3ccode\x3elat\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",
+
+    'pixelAddError': "Do moß beeds \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",
+
+    'unsupportedGeometryType': "De Zoot Jommetrii dom_mer nit ongershtöze: \x3ccode\x3e${geomType}\x3c/code\x3e",
+
+    'pagePositionFailed': "\x3ccode lang=\"en\"\x3eOpenLayers.Util.pagePosition\x3c/code\x3e es donevve jejange: dat Denge met dä Kännong \x3ccode\x3e${elemId}\x3c/code\x3e künnt am verkeehte Plaz sin.",
+
+    'filterEvaluateNotImplemented': "„\x3ccode lang=\"en\"\x3eevaluate\x3c/code\x3e“ es för di Zoot Fellter nit enjereschdt."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/nb.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/nb.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/nb.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,20 +1,16 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */
 
 /**
  * Namespace: OpenLayers.Lang["nb"]
- * Dictionary for norwegian bokmål (Norway). Keys for entries are used in calls to
+ * Dictionary for norwegian bokmål (Norway). Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
 OpenLayers.Lang["nb"] = {
 
-    'unhandledRequest': "Ubehandlet forespørsel returnerte ${statusText}",
+    'unhandledRequest': "Ubehandlet forespørsel returnerte ${statusText}",
 
     'permalink': "Kobling til denne siden",
 
@@ -23,61 +19,61 @@
     'baseLayer': "Bakgrunnskart",
 
     'sameProjection':
-        "Oversiktskartet fungerer bare når det har samme projeksjon som hovedkartet",
+        "Oversiktskartet fungerer bare når det har samme projeksjon som hovedkartet",
 
     'readNotImplemented': "Lesing er ikke implementert.",
 
     'writeNotImplemented': "Skriving er ikke implementert.",
 
-    'noFID': "Kan ikke oppdatere feature (objekt) som ikke har FID.",
+    'noFID': "Kan ikke oppdatere et feature (et objekt) som ikke har FID.",
 
     'errorLoadingGML': "Feil under lasting av GML-fil ${url}",
 
     'browserNotSupported':
-        "Din nettleser støtter ikke vektortegning. Følgende tegnemetoder støttes:\n${renderers}",
+        "Din nettleser støtter ikke vektortegning. Tegnemetodene som støttes er:\n${renderers}",
 
-    'componentShouldBe': "addFeatures : komponenten må være en ${geomType}",
+    'componentShouldBe': "addFeatures : komponenten må være en ${geomType}",
 
     // console message
     'getFeatureError':
-        "getFeatureFromEvent kjørt mot lag uten tegnemetode. Dette betyr som regel at du " +
-        "fjernet et lag uten å fjerne alle handlere tilknyttet laget.",
+        "getFeatureFromEvent har blitt kjørt mot et lag uten noen tegnemetode. Dette betyr som regel at du " +
+        "fjernet et lag uten å fjerne alle håndterere tilknyttet laget.",
 
     // console message
     'minZoomLevelError':
-        "Egenskapen minZoomLevel er kun tenkt for bruk på lag " +
-        "basert på FixedZoomLevels. At dette wfs-laget sjekker " +
-        "minZoomLevel er en fortidslevning. Det kan dog ikke " +
-        "tas bort uten å risikere at OL-baserte applikasjoner " +
-        "slutter å virke, så det er merket som foreldet: " +
+        "Egenskapen minZoomLevel er kun ment til bruk på lag " +
+        "basert på FixedZoomLevels. At dette wfs-laget sjekker " +
+        "minZoomLevel er en etterlevning fra tidligere versjoner. Det kan dog ikke " +
+        "tas bort uten å risikere at OL-baserte applikasjoner " +
+        "slutter å virke, så det er merket som foreldet: " +
         "minZoomLevel i sjekken nedenfor vil fjernes i 3.0. " +
-        "Vennligst bruk innstillingene for min/maks oppløsning " +
+        "Vennligst bruk innstillingene for min/maks oppløsning " +
         "som er beskrevet her: "+
         "http://trac.openlayers.org/wiki/SettingZoomLevels",
 
-    'commitSuccess': "WFS-transaksjon: SUKSESS ${response}",
+    'commitSuccess': "WFS-transaksjon: LYKTES ${response}",
 
-    'commitFailed': "WFS-transaksjon: FEILET ${response}",
+    'commitFailed': "WFS-transaksjon: MISLYKTES ${response}",
 
     'googleWarning':
         "Google-laget kunne ikke lastes.<br><br>" +
         "Bytt til et annet bakgrunnslag i lagvelgeren i " +
-        "øvre høyre hjørne for å slippe denne meldingen.<br><br>" +
-        "Sannsynligvis forårsakes feilen av at Google Maps-biblioteket " +
-        "ikke er riktig inkludert på nettsiden, eller at det ikke er " +
-        "angitt riktig API-nøkkel for nettstedet.<br><br>" +
-        "Utviklere: For hjelp til å få dette til å virke se "+
+        "øvre høyre hjørne for å slippe denne meldingen.<br><br>" +
+        "Sannsynligvis forårsakes feilen av at Google Maps-biblioteket " +
+        "ikke er riktig inkludert på nettsiden, eller at det ikke er " +
+        "angitt riktig API-nøkkel for nettstedet.<br><br>" +
+        "Utviklere: For hjelp til å få dette til å virke se "+
         "<a href='http://trac.openlayers.org/wiki/Google' " +
         "target='_blank'>her</a>.",
 
     'getLayerWarning':
         "${layerType}-laget kunne ikke lastes.<br><br>" +
         "Bytt til et annet bakgrunnslag i lagvelgeren i " +
-        "øvre høyre hjørne for å slippe denne meldingen.<br><br>" +
-        "Sannsynligvis forårsakes feilen av at " +
+        "øvre høyre hjørne for å slippe denne meldingen.<br><br>" +
+        "Sannsynligvis forårsakes feilen av at " +
         "${layerLib}-biblioteket ikke var riktig inkludert " +
-        "på nettsiden.<br><br>" +
-        "Utviklere: For hjelp til å få dette til å virke se " +
+        "på nettsiden.<br><br>" +
+        "Utviklere: For hjelp til å få dette til å virke se " +
         "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
         "target='_blank'>her</a>.",
 
@@ -85,36 +81,38 @@
 
     // console message
     'layerAlreadyAdded':
-        "Du forsøkte å legge til laget ${layerName} på kartet, men det er allerede lagt til",
+        "Du forsøkte å legge til laget ${layerName} på kartet, men det er allerede lagt til",
 
     // console message
     'reprojectDeprecated':
-        "Du bruker innstillingen 'reproject' på laget ${layerName}. " +
-        "Denne innstillingen er foreldet, den var ment for å støtte " +
+        "Du bruker innstillingen 'reproject' på laget ${layerName}. " +
+        "Denne innstillingen er foreldet, den var ment for å støtte " +
         "visning av kartdata over kommersielle bakgrunnskart, men det " +
-        "bør nå gjøres med støtten for Spherical Mercator. Mer informasjon " +
-        "finnes på http://trac.openlayers.org/wiki/SphericalMercator.",
+        "bør nå gjøres med støtten for Spherical Mercator. Mer informasjon " +
+        "finnes på http://trac.openlayers.org/wiki/SphericalMercator.",
 
     // console message
     'methodDeprecated':
         "Denne metoden er markert som foreldet og vil bli fjernet i 3.0. " +
-        "Bruk ${newMethod} i stedet.",
+        "Vennligst bruk ${newMethod} i stedet.",
 
     // console message
-    'boundsAddError': "Du må gi både x- og y-verdier til funksjonen add.",
+    'boundsAddError': "Du må gi både x- og y-verdier til funksjonen add.",
 
     // console message
-    'lonlatAddError': "Du må gi både lon- og lat-verdier til funksjonen add.",
+    'lonlatAddError': "Du må gi både lon- og lat-verdier til funksjonen add.",
 
     // console message
-    'pixelAddError': "Du må gi både x- og y-verdier til funksjonen add.",
+    'pixelAddError': "Du må gi både x- og y-verdier til funksjonen add.",
 
     // console message
-    'unsupportedGeometryType': "Ustøttet geometritype: ${geomType}",
+    'unsupportedGeometryType': "Geometritypen ${geomType} er ikke støttet",
 
     // console message
     'pagePositionFailed':
-        "OpenLayers.Util.pagePosition feilet: elementet med id ${elemId} kan være feilplassert.",
+        "OpenLayers.Util.pagePosition feilet: elementet med id ${elemId} kan være feilplassert.",
                     
     'end': ''
 };
+
+OpenLayers.Lang["no"] = OpenLayers.Lang["nb"];

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/nds.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/nds.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/nds.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/nds.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,61 @@
+/* Translators (2009 onwards):
+ *  - Slomox
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["nds"]
+ * Dictionary for Plattdüütsch.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["nds"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Unbehannelt Trüchmellels för de Anfraag ${statusText}",
+
+    'permalink': "Permalink",
+
+    'overlays': "Overlays",
+
+    'baseLayer': "Achtergrundkoort",
+
+    'sameProjection': "De Översichtskoort geiht blot, wenn de sülve Projekschoon as bi de Hööftkoort bruukt warrt",
+
+    'readNotImplemented': "Lesen is nich inricht.",
+
+    'writeNotImplemented': "Schrieven is nich inricht.",
+
+    'noFID': "En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",
+
+    'errorLoadingGML': "Fehler bi’t Laden vun de GML-Datei ${url}",
+
+    'browserNotSupported': "Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",
+
+    'componentShouldBe': "addFeatures : Kumponent schull man den Typ ${geomType} hebben",
+
+    'getFeatureError': "getFeatureFromEvent is von en Laag ahn Render opropen worrn. Dat bedüüdt normalerwies, dat en Laag wegmaakt worrn is, aver nich de Handler, de dor op verwiest.",
+
+    'commitSuccess': "WFS-Transakschoon: hett klappt ${response}",
+
+    'commitFailed': "WFS-Transakschoon: hett nich klappt ${response}",
+
+    'scale': "Skaal = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Du versöchst de Laag „${layerName}“ to de Koort totofögen, man de is al toföögt",
+
+    'methodDeprecated': "Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för.",
+
+    'boundsAddError': "De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",
+
+    'lonlatAddError': "De Weert lon un lat, de mööt all beid an de add-Funkschoon övergeven warrn.",
+
+    'pixelAddError': "De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",
+
+    'unsupportedGeometryType': "Nich ünnerstütt Geometrie-Typ: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition güng nich: Element mit de Id ${elemId} is villicht an’n verkehrten Platz."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/nl.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/nl.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/nl.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,68 +1,79 @@
-/* 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. */
+/* Translators (2009 onwards):
+ *  - Siebrand
+ */
 
 /**
- * @requires OpenLayers/Lang/en.js
+ * @requires OpenLayers/Lang.js
  */
 
 /**
  * Namespace: OpenLayers.Lang["nl"]
- * Dictionary for Dutch.  Keys for entries are used in calls to
+ * Dictionary for Nederlands.  Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
-OpenLayers.Lang.nl = OpenLayers.Util.applyDefaults({
+OpenLayers.Lang["nl"] = OpenLayers.Util.applyDefaults({
 
-    'unhandledRequest': "Niet afgehandeld request met als terugmelding ${statusText}",
+    'unhandledRequest': "Het verzoek is niet afgehandeld met de volgende melding: ${statusText}",
 
-    'permalink': "Permalink",
+    'permalink': "Permanente verwijzing",
 
     'overlays': "Overlays",
 
     'baseLayer': "Achtergrondkaart",
 
-    'sameProjection':
-        "De overzichtskaart werkt alleen als de projectie gelijk is aan de projectie van de hoofdkaart",
+    'sameProjection': "De overzichtskaart werkt alleen als de projectie gelijk is aan de projectie van de hoofdkaart",
 
-    'readNotImplemented': "Lezen niet geïmplementeerd.",
+    'readNotImplemented': "Lezen is niet geïmplementeerd.",
 
-    'writeNotImplemented': "Schrijven niet geïmplementeerd.",
+    'writeNotImplemented': "Schrijven is niet geïmplementeerd.",
 
-    'noFID': "Een feature welke geen FID heeft kan niet bijgewerkt worden.",
+    'noFID': "Een optie die geen FID heeft kan niet bijgewerkt worden.",
 
-    'errorLoadingGML': "Fout bij het laden van GML bestand ${url}",
+    'errorLoadingGML': "Er is een fout opgetreden bij het laden van het GML bestand van ${url}",
 
-    'browserNotSupported':
-        "Uw browser ondersteunt het weergeven van vector niet. Momenteel ondersteunde weergave engines:\n${renderers}",
+    'browserNotSupported': "Uw browser ondersteunt het weergeven van vectoren niet.\nMomenteel ondersteunde weergavemogelijkheden:\n${renderers}",
 
-    'componentShouldBe': "addFeatures : component zou van het type ${geomType} moeten zijn",
+    'componentShouldBe': "addFeatures : component moet van het type ${geomType} zijn",
 
-    'commitSuccess': "WFS-transactie: SUCCESVOL ${response}",
+    'getFeatureError': "getFeatureFromEvent is aangeroepen op een laag zonder rederer.\nDit betekent meestal dat u een laag hebt verwijderd, maar niet een handler die ermee geassocieerd was.",
 
-    'commitFailed': "WFS-transactie: MISLUKT ${response}",
+    'minZoomLevelError': "De eigenschap minZoomLevel is alleen bedoeld voor gebruik lagen met die afstammen van FixedZoomLevels-lagen.\nDat deze WFS-laag minZoomLevel controleert, is een overblijfsel uit het verleden.\nWe kunnen deze controle echter niet verwijderen zonder op OL gebaseerde applicaties die hervan afhankelijk zijn stuk te maken.\nDaarom heeft deze functionaliteit de eigenschap \'deprecated\' gekregen - de minZoomLevel wordt verwijderd in versie 3.0.\nGebruik in plaats van deze functie de mogelijkheid om min/max voor resolutie in te stellen zoals op de volgende pagina wordt beschreven:\nhttp://trac.openlayers.org/wiki/SettingZoomLevels",
 
-    'googleWarning':
-        "De Google-Layer kon niet correct geladen worden.<br><br>" +
-        "Om deze melding niet meer te krijgen, moet u een andere " +
-        "achtergrondkaart kiezen in de LayerSwitcher in de rechterbovenhoek.<br><br>" +
-        "Dit is waarschijnlijk omdat de ${layerLib} bilbiotheek " +
-        "niet correct ingevoegd is.<br><br>" +
-        "Ontwikkelaars: om dit werkend te krijgen, " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>klik hier</a>",
+    'commitSuccess': "WFS-transactie: succesvol ${response}",
 
-    'getLayerWarning':
-        "De ${layerType} Layer kon niet goed geladen worden.<br><br>" +
-        "Om deze melding niet meer te krijgen, moet u een andere " +
-        "achtergrondkaart kiezen in de LayerSwitcher in de rechterbovenhoek.<br><br>" +
-        "Dit is waarschijnlijk omdat de ${layerLib} bilbiotheek " +
-        "niet correct ingevoegd is.<br><br>" +
-        "Ontwikkelaars: om dit werkend te krijgen, " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>klik hier</a>",
+    'commitFailed': "WFS-transactie: mislukt ${response}",
 
+    'googleWarning': "De Google-Layer kon niet correct geladen worden.\x3cbr /\x3e\x3cbr /\x3e\nOm deze melding niet meer te krijgen, moet u een andere achtergrondkaart kiezen in de laagwisselaar in de rechterbovenhoek.\x3cbr /\x3e\x3cbr /\x3e\nDit komt waarschijnlijk doordat de bibliotheek ${layerLib} niet correct ingevoegd is.\x3cbr /\x3e\x3cbr /\x3e\nOntwikkelaars: \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik hier\x3c/a\x3e om dit werkend te krijgen.",
+
+    'getLayerWarning': "De laag ${layerType} kon niet goed geladen worden.\x3cbr /\x3e\x3cbr /\x3e\nOm deze melding niet meer te krijgen, moet u een andere achtergrondkaart kiezen in de laagwisselaar in de rechterbovenhoek.\x3cbr /\x3e\x3cbr /\x3e\nDit komt waarschijnlijk doordat de bibliotheek ${layerLib} niet correct is ingevoegd.\x3cbr /\x3e\x3cbr /\x3e\nOntwikkelaars: \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik hier\x3c/a\x3e om dit werkend te krijgen.",
+
     'scale': "Schaal = 1 : ${scaleDenom}",
 
-    'end': ''
-}, OpenLayers.Lang["en"]);
+    'W': "W",
+
+    'E': "O",
+
+    'N': "N",
+
+    'S': "Z",
+
+    'layerAlreadyAdded': "U hebt geprobeerd om de laag  ${layerName} aan de kaart toe te voegen, maar deze is al toegevoegd",
+
+    'reprojectDeprecated': "U gebruikt de optie \'reproject\' op de laag ${layerName}.\nDeze optie is vervallen: deze optie was ontwikkeld om gegevens over commerciële basiskaarten weer te geven, maar deze functionaliteit wordt nu bereikt door ondersteuning van Spherical Mercator.\nMeer informatie is beschikbaar op http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Deze methode is verouderd en wordt verwijderd in versie 3.0.\nGebruik ${newMethod}.",
+
+    'boundsAddError': "U moet zowel de x- als de y-waarde doorgeven aan de toevoegfunctie.",
+
+    'lonlatAddError': "U moet zowel de lengte- als de breedtewaarde doorgeven aan de toevoegfunctie.",
+
+    'pixelAddError': "U moet zowel de x- als de y-waarde doorgeven aan de toevoegfunctie.",
+
+    'unsupportedGeometryType': "Dit geometrietype wordt niet ondersteund: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition is mislukt: het element met id ${elemId} is wellicht onjuist geplaatst.",
+
+    'filterEvaluateNotImplemented': "evalueren is niet geïmplementeerd voor dit filtertype."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/nn.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/nn.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/nn.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/nn.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,27 @@
+/* Translators (2009 onwards):
+ *  - Harald Khan
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["nn"]
+ * Dictionary for ‪Norsk (nynorsk)‬.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["nn"] = OpenLayers.Util.applyDefaults({
+
+    'scale': "Skala = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Du freista å leggja til laget «${layerName}» på kartet, men det har alt vorte lagt til.",
+
+    'boundsAddError': "Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen.",
+
+    'lonlatAddError': "Du er nøydd til å gje både lon- og lat-verdiar til «add»-funksjonen.",
+
+    'pixelAddError': "Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/oc.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/oc.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/oc.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/oc.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Cedric31
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["oc"]
+ * Dictionary for Occitan.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["oc"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Requèsta pas gerida, retorna ${statusText}",
+
+    'permalink': "Permaligam",
+
+    'overlays': "Calques",
+
+    'baseLayer': "Calc de basa",
+
+    'sameProjection': "La carta de situacion fonciona pas que quora sa projeccion es la meteissa que la de la carta principala",
+
+    'readNotImplemented': "Lectura pas implementada.",
+
+    'writeNotImplemented': "Escritura pas implementada.",
+
+    'noFID': "Impossible de metre a jorn un objècte sens identificant (fid).",
+
+    'errorLoadingGML': "Error al cargament del fichièr GML ${url}",
+
+    'browserNotSupported': "Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",
+
+    'componentShouldBe': "addFeatures : lo compausant deuriá èsser de tipe ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent es estat apelat sus un calc sens renderer. Aquò significa generalament qu\'avètz destruch aqueste jaç, mas qu\'avètz conservat un handler que li èra associat.",
+
+    'minZoomLevelError': "La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà, la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Transaccion WFS : SUCCES ${response}",
+
+    'commitFailed': "Transaccion WFS : FRACAS ${response}",
+
+    'googleWarning': "Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",
+
+    'getLayerWarning': "Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una  BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquí, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",
+
+    'scale': "Escala ~ 1 : ${scaleDenom}",
+
+    'W': "O",
+
+    'E': "È",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Avètz ensajat d\'apondre a la carta lo calc : ${layerName}, mas ja es present",
+
+    'reprojectDeprecated': "Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça.",
+
+    'boundsAddError': "Vos cal passar las doas valors x e y a la foncion add.",
+
+    'lonlatAddError': "Vos cal passar las doas valors lon e lat a la foncion add.",
+
+    'pixelAddError': "Vos cal passar las doas valors x e y a la foncion add.",
+
+    'unsupportedGeometryType': "Tipe de geometria pas suportat : ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition a fracassat : l\'element d\'id ${elemId} poiriá èsser mal posicionat.",
+
+    'filterEvaluateNotImplemented': "evaluar es pas encara estat implementat per aqueste tipe de filtre."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt-BR.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt-BR.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt-BR.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,18 +1,19 @@
-/* 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. */
+/* Translators (2009 onwards):
+ *  - Luckas Blade
+ *  - Rodrigo Avila
+ */
 
 /**
  * @requires OpenLayers/Lang.js
  */
 
 /**
- * Namespace: OpenLayers.Lang["pt-BR"]
- * Dictionary for Brazilian Portuguese.  Keys for entries are used in calls to
+ * Namespace: OpenLayers.Lang["pt-br"]
+ * Dictionary for Português do Brasil.  Keys for entries are used in calls to
  *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
  *     strings formatted for use with <OpenLayers.String.format> calls.
  */
-OpenLayers.Lang["pt-BR"] = {
+OpenLayers.Lang["pt-br"] = OpenLayers.Util.applyDefaults({
 
     'unhandledRequest': "A requisição retornou um erro não tratado: ${statusText}",
 
@@ -22,8 +23,7 @@
 
     'baseLayer': "Camada Base",
 
-    'sameProjection':
-        "O mapa de referência só funciona quando ele está na mesma projeção do mapa principal",
+    'sameProjection': "O mapa de referência só funciona quando ele está na mesma projeção do mapa principal",
 
     'readNotImplemented': "Leitura não implementada.",
 
@@ -33,90 +33,48 @@
 
     'errorLoadingGML': "Erro ao carregar o arquivo GML ${url}",
 
-    'browserNotSupported':
-        "Seu navegador não suporta renderização de vetores. Os renderizadores suportados atualmente são:\n${renderers}",
+    'browserNotSupported': "Seu navegador não suporta renderização de vetores. Os renderizadores suportados atualmente são:\n${renderers}",
 
     'componentShouldBe': "addFeatures: o componente deve ser do tipo ${geomType}",
 
-    // console message
-    'getFeatureError':
-        "getFeatureFromEvent foi executado mas nenhum renderizador foi encontrado. " +
-        "Isso pode indicar que você destruiu uma camana, mas não o handler associado a ela.",
+    'getFeatureError': "getFeatureFromEvent foi executado mas nenhum renderizador foi encontrado. Isso pode indicar que você destruiu uma camana, mas não o handler associado a ela.",
 
-    // console message
-    'minZoomLevelError':
-        "A propriedade minZoomLevel é de uso restrito das camadas "+
-        "descendentes de FixedZoomLevels. A verificação dessa propriedade " +
-        "pelas camadas wfs é um resíduo do passado. Não podemos, entretanto " +
-        "não é possível removê-la sem possívelmente quebrar o funcionamento " +
-        "de aplicações OL que possuem depência com ela. Portanto estamos " +
-        "tornando seu uso obsoleto -- a verificação desse atributo será " +
-        "removida na versão 3.0. Ao invés, use as opções de resolução " +
-        "min/max como descrito em: " +
-        "http://trac.openlayers.org/wiki/SettingZoomLevels",
+    'minZoomLevelError': "A propriedade minZoomLevel é de uso restrito das camadas descendentes de FixedZoomLevels. A verificação dessa propriedade pelas camadas wfs é um resíduo do passado. Não podemos, entretanto não é possível removê-la sem possívelmente quebrar o funcionamento de aplicações OL que possuem depência com ela. Portanto estamos tornando seu uso obsoleto -- a verificação desse atributo será removida na versão 3.0. Ao invés, use as opções de resolução min/max como descrito em: http://trac.openlayers.org/wiki/SettingZoomLevels",
 
     'commitSuccess': "Transação WFS : SUCESSO ${response}",
 
     'commitFailed': "Transação WFS : ERRO ${response}",
 
-    'googleWarning':
-        "Não foi possível carregar a camada Google corretamente.<br><br>" +
-        "Para se livrar dessa mensagem, selecione uma nova Camada Base, " +
-        "na ferramenta de alternação de camadas localização do canto " +
-        "superior direito.<br><br>" +
-        "Muito provavelmente, isso foi causado porque o script da " +
-        "biblioteca do Google Maps não foi incluído, ou porque ele não " +
-        "contém a chave correta da API para o seu site.<br><br>" +
-        "Desenvolvedores: Para obter ajuda em solucionar esse problema " +
-        "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>cliquem aqui</a>",
+    'googleWarning': "Não foi possível carregar a camada Google corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca do Google Maps não foi incluído, ou porque ele não contém a chave correta da API para o seu site.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",
 
-    'getLayerWarning':
-        "Não foi possível carregar a camada ${layerType} corretamente.<br><br>" +
-        "Para se livrar dessa mensagem, selecione uma nova Camada Base, " +
-        "na ferramenta de alternação de camadas localização do canto " +
-        "superior direito.<br><br>" +
-        "Muito provavelmente, isso foi causado porque o script da " +
-        "biblioteca ${layerLib} não foi incluído corretamente.<br><br>" +
-        "Desenvolvedores: Para obter ajuda em solucionar esse problema " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>cliquem aqui</a>",
+    'getLayerWarning': "Não foi possível carregar a camada ${layerType} corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca ${layerLib} não foi incluído corretamente.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",
 
     'scale': "Escala = 1 : ${scaleDenom}",
 
-    // console message
-    'layerAlreadyAdded':
-        "Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já foi adicionada",
+    'W': "O",
 
-    // console message
-    'reprojectDeprecated':
-        "Você está usando a opção 'reproject' na camada ${layerName}. " +
-        "Essa opção está obsoleta: seu uso foi projetado para suportar " +
-        "a visualização de dados sobre bases de mapas comerciais, " +
-        "entretanto essa funcionalidade deve agora ser alcançada usando " +
-        "o suporte à projeção Mercator. Mais informação está disponível em: " +
-        "http://trac.openlayers.org/wiki/SphericalMercator.",
+    'E': "L",
 
-    // console message
-    'methodDeprecated':
-        "Esse método está obsoleto e será removido na versão 3.0. " +
-        "Ao invés, por favor use ${newMethod}.",
+    'N': "N",
 
-    // console message
+    'S': "S",
+
+    'layerAlreadyAdded': "Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já foi adicionada",
+
+    'reprojectDeprecated': "Você está usando a opção \'reproject\' na camada ${layerName}. Essa opção está obsoleta: seu uso foi projetado para suportar a visualização de dados sobre bases de mapas comerciais, entretanto essa funcionalidade deve agora ser alcançada usando o suporte à projeção Mercator. Mais informação está disponível em: http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Esse método está obsoleto e será removido na versão 3.0. Ao invés, por favor use ${newMethod}.",
+
     'boundsAddError': "Você deve informar ambos os valores x e y para a função add.",
 
-    // console message
     'lonlatAddError': "Você deve informar ambos os valores lon e lat para a função add.",
 
-    // console message
     'pixelAddError': "Você deve informar ambos os valores x e y para a função add.",
 
-    // console message
     'unsupportedGeometryType': "Tipo geométrico não suportado: ${geomType}.",
 
-    // console message
-    'pagePositionFailed':
-        "OpenLayers.Util.pagePosition falhou: o elemento de id ${elemId} deve estar fora do lugar.",
-                    
-    'end': ''
-};
+    'pagePositionFailed': "OpenLayers.Util.pagePosition falhou: o elemento de id ${elemId} deve estar fora do lugar.",
+
+    'filterEvaluateNotImplemented': "evaluete não está implementado para este tipo de filtro."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/pt.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/pt.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,81 @@
+/* Translators (2009 onwards):
+ *  - Hamilton Abreu
+ *  - Malafaya
+ *  - Waldir
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["pt"]
+ * Dictionary for Português.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["pt"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Servidor devolveu erro não contemplado ${statusText}",
+
+    'permalink': "Ligação permanente",
+
+    'overlays': "Sobreposições",
+
+    'baseLayer': "Camada Base",
+
+    'sameProjection': "O mapa panorâmico só funciona quando está na mesma projeção que o mapa principal",
+
+    'readNotImplemented': "Leitura não implementada.",
+
+    'writeNotImplemented': "Escrita não implementada.",
+
+    'noFID': "Não é possível atualizar um elemento para a qual não há FID.",
+
+    'errorLoadingGML': "Erro ao carregar ficheiro GML ${url}",
+
+    'browserNotSupported': "O seu navegador não suporta renderização vetorial. Actualmente os renderizadores suportados são:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: componente deve ser um(a) ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent foi chamado numa camada sem renderizador. Isto normalmente significa que destruiu uma camada, mas não um manipulador \'\'(handler)\'\' que lhe está associado.",
+
+    'minZoomLevelError': "A propriedade minZoomLevel só deve ser usada com as camadas descendentes da FixedZoomLevels. A verificação da propriedade por esta camada wfs é uma relíquia do passado. No entanto, não podemos removê-la sem correr o risco de afectar aplicações OL que dependam dela. Portanto, estamos a torná-la obsoleta -- a verificação minZoomLevel será removida na versão 3.0. Em vez dela, por favor, use as opções de resolução min/max descritas aqui: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Transacção WFS: SUCESSO ${response}",
+
+    'commitFailed': "Transacção WFS: FALHOU ${response}",
+
+    'googleWarning': "A Camada Google não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara deixar de receber esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca do Google Maps não foi incluído ou não contém a chave API correcta para o seu sítio.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",
+
+    'getLayerWarning': "A camada ${layerType} não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara desactivar esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca ${layerLib} não foi incluído correctamente.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",
+
+    'scale': "Escala = 1 : ${scaleDenom}",
+
+    'W': "O",
+
+    'E': "E",
+
+    'N': "N",
+
+    'S': "S",
+
+    'layerAlreadyAdded': "Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já tinha sido adicionada antes",
+
+    'reprojectDeprecated': "Está usando a opção \'reproject\' na camada ${layerName}. Esta opção é obsoleta: foi concebida para permitir a apresentação de dados sobre mapas-base comerciais, mas esta funcionalidade é agora suportada pelo Mercator Esférico. Mais informação está disponível em http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Este método foi declarado obsoleto e será removido na versão 3.0. Por favor, use ${newMethod} em vez disso.",
+
+    'boundsAddError': "Você deve passar tanto o valor x como o y à função de adição.",
+
+    'lonlatAddError': "Você deve passar tanto o valor lon como o lat à função de adição.",
+
+    'pixelAddError': "Você deve passar tanto o valor x como o y à função de adição.",
+
+    'unsupportedGeometryType': "Tipo de geometria não suportado: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition falhou: o elemento com o id ${elemId} poderá estar mal-posicionado.",
+
+    'filterEvaluateNotImplemented': "avaliar não está implementado para este tipo de filtro."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/ru.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/ru.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/ru.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/ru.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,82 @@
+/* Translators (2009 onwards):
+ *  - Ferrer
+ *  - Komzpa
+ *  - Lockal
+ *  - Александр Сигачёв
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["ru"]
+ * Dictionary for Русский.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["ru"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Необработанный запрос вернул ${statusText}",
+
+    'permalink': "Постоянная ссылка",
+
+    'overlays': "Слои",
+
+    'baseLayer': "Основной слой",
+
+    'sameProjection': "Обзорная карта работает только тогда, когда имеет ту же проекцию, что и основная",
+
+    'readNotImplemented': "Чтение не реализовано.",
+
+    'writeNotImplemented': "Запись не реализована.",
+
+    'noFID': "Невозможно обновить объект, для которого нет FID.",
+
+    'errorLoadingGML': "Ошибка при загрузке файла GML ${url}",
+
+    'browserNotSupported': "Ваш браузер не поддерживает векторную графику. На данный момент поддерживаются:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: компонент должен быть ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent вызван для слоя без рендерера. Обычно это говорит о том, что вы уничтожили слой, но оставили связанный с ним обработчик.",
+
+    'minZoomLevelError': "Свойство minZoomLevel предназначено только для использования со слоями, являющимися потомками FixedZoomLevels. То, что этот WFS-слой проверяется на minZoomLevel — реликт прошлого. Однако мы не можем удалить эту функцию, так как, возможно, от неё зависят некоторые основанные на OpenLayers приложения. Функция объявлена устаревшей — проверка minZoomLevel будет удалена в 3.0. Пожалуйста, используйте вместо неё настройку мин/макс разрешения, описанную здесь: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Транзакция WFS: УСПЕШНО ${response}",
+
+    'commitFailed': "Транзакция WFS: ОШИБКА ${response}",
+
+    'googleWarning': "Слой Google не удалось нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека Google Maps не была включена или не содержит корректного API-ключа для вашего сайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",
+
+    'getLayerWarning': "Слой ${layerType} не удалось нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",
+
+    'scale': "Масштаб = 1 : ${scaleDenom}",
+
+    'W': "З",
+
+    'E': "Ð’",
+
+    'N': "С",
+
+    'S': "Ю",
+
+    'layerAlreadyAdded': "Вы попытались добавить слой «${layerName}» на карту, но он уже был добавлен",
+
+    'reprojectDeprecated': "Вы используете опцию \'reproject\' для слоя ${layerName}. Эта опция является устаревшей: ее использование предполагалось для поддержки показа данных поверх коммерческих базовых карт, но теперь этот функционал несёт встроенная поддержка сферической проекции Меркатора. Больше сведений доступно на http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Этот метод считается устаревшим и будет удалён в версии 3.0. Пожалуйста, пользуйтесь ${newMethod}.",
+
+    'boundsAddError': "Функции add надо передавать оба значения, x и y.",
+
+    'lonlatAddError': "Функции add надо передавать оба значения, lon и lat.",
+
+    'pixelAddError': "Функции add надо передавать оба значения, x и y.",
+
+    'unsupportedGeometryType': "Неподдерживаемый тип геометрии: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition failed: элемент с id ${elemId} может находиться не в нужном месте.",
+
+    'filterEvaluateNotImplemented': "evaluate не реализовано для фильтра данного типа."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/sk.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/sk.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/sk.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/sk.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,71 @@
+/* Translators (2009 onwards):
+ *  - Helix84
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["sk"]
+ * Dictionary for Slovenčina.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["sk"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Neobslúžené požiadavky vracajú ${statusText}",
+
+    'permalink': "Trvalý odkaz",
+
+    'overlays': "Prekrytia",
+
+    'baseLayer': "Základná vrstva",
+
+    'sameProjection': "Prehľadová mapka funguje iba vtedy, keď je v rovnakej projekcii ako hlavná mapa",
+
+    'readNotImplemented': "Čítanie nie je implementované.",
+
+    'writeNotImplemented': "Zápis nie je implementovaný.",
+
+    'noFID': "Nie je možné aktualizovať vlastnosť, pre ktorú neexistuje FID.",
+
+    'errorLoadingGML': "Chyba pri načítaní súboru GML ${url}",
+
+    'browserNotSupported': "Váš prehliadač nepodporuje vykresľovanie vektorov. Momentálne podporované vykresľovače sú:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: komponent by mal byť ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent bola zavolaná na vrstve bez vykresľovača. To zvyčajne znamená, že ste odstránili vrstvu, ale nie niektorú z obslúh, ktorá je s ňou asociovaná.",
+
+    'minZoomLevelError': "Vlastnosť minZoomLevel je určený iba na použitie s vrstvami odvodenými od FixedZoomLevels. To, že táto wfs vrstva kontroluje minZoomLevel je pozostatok z minulosti. Nemôžeme ho však odstrániť, aby sme sa vyhli možnému porušeniu aplikácií založených na Open Layers, ktoré na tomto môže závisieť. Preto ho označujeme ako zavrhovaný - dolu uvedená kontrola minZoomLevel bude odstránená vo verzii 3.0. Použite prosím namiesto toho kontrolu min./max. rozlíšenia podľa tu uvedeného popisu: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Transakcia WFS: ÚSPEŠNÁ ${response}",
+
+    'commitFailed': "Transakcia WFS: ZLYHALA ${response}",
+
+    'googleWarning': "Vrstvu Google nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice Google Maps buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",
+
+    'getLayerWarning': "Vrstvu ${layerType} nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice ${layerType} buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/${layerType}\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",
+
+    'scale': "Mierka = 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Pokúsili ste sa do mapy pridať vrstvu ${layerName}, ale tá už bola pridaná",
+
+    'reprojectDeprecated': "Používate voľby „reproject“ vrstvy ${layerType}. Táto voľba je zzavrhovaná: jej použitie bolo navrhnuté na podporu zobrazovania údajov nad komerčnými základovými mapami, ale túto funkcionalitu je teraz možné dosiahnuť pomocou Spherical Mercator. Ďalšie informácie získate na stránke http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Táto metóda je zavrhovaná a bude odstránená vo verzii 3.0. Použite prosím namiesto nej metódu ${newMethod}.",
+
+    'boundsAddError': "Sčítacej funkcii musíte dať hodnoty x aj y.",
+
+    'lonlatAddError': "Sčítacej funkcii musíte dať hodnoty lon (zem. dĺžka) aj lat (zem. šírka).",
+
+    'pixelAddError': "Sčítacej funkcii musíte dať hodnoty x aj y.",
+
+    'unsupportedGeometryType': "Nepodporovaný typ geometrie: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition zlyhalo: prvok s id ${elemId} môže byť zle umiestnený.",
+
+    'filterEvaluateNotImplemented': "evaluate nie je implementovaný pre tento typ filtra"
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/sv-SE.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/sv-SE.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/sv-SE.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,121 +1,71 @@
-/* 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. */
-
-/**
- * @requires OpenLayers/Lang.js
- */
-
-/**
- * Namespace: OpenLayers.Lang["sv-SE"]
- * Dictionary for swedish (Sweden).  Keys for entries are used in calls to
- *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
- *     strings formatted for use with <OpenLayers.String.format> calls.
- */
-OpenLayers.Lang["sv-SE"] = {
-
-    'unhandledRequest': "Ej hanterad fr�ga retur ${statusText}",
-
-    'permalink': "Permal�nk",
-
-    'overlays': "Kartlager",
-
-    'baseLayer': "Bakgrundskarta",
-
-    'sameProjection':
-        "�versiktskartan fungerar endast n�r den har samma projektion som huvudkartan",
-
-    'readNotImplemented': "L�sning ej implementerad.",
-
-    'writeNotImplemented': "Skrivning ej implementerad.",
-
-    'noFID': "Kan ej uppdatera feature (objekt) f�r vilket FID saknas.",
-
-    'errorLoadingGML': "Fel i laddning av GML-fil ${url}",
-
-    'browserNotSupported':
-        "Din webbl�sare st�der inte vektorvisning. F�r n�rvarande st�ds f�ljande visning:\n${renderers}",
-
-    'componentShouldBe': "addFeatures : komponenten skall vara en ${geomType}",
-
-    // console message
-    'getFeatureError':
-        "getFeatureFromEvent anropad f�r lager utan utritning. Detta betyder oftast att man " +
-        "raderat ett lager, men inte en hanterare som �r knuten till lagret.",
-
-    // console message
-    'minZoomLevelError':
-        "Egenskapen minZoomLevel �r endast avsedd att anv�ndas " +
-        "med lager med FixedZoomLevels. Att detta WFS-lager " +
-        "kontrollerar minZoomLevel �r en relik fr�n �ldre versioner. " +
-        "Vi kan dock inte ta bort det utan att riskera att " +
-        "OL-baserade till�mpningar som anv�nder detta slutar " +
-        "fungera. D�rf�r �r det satt som deprecated, minZoomLevel " +
-        "kommer att tas bort i version 3.0. Anv�nd i st�llet " +
-        "inst�llning av min/max resolution som beskrivs h�r: " +
-        "http://trac.openlayers.org/wiki/SettingZoomLevels",
-
-    'commitSuccess': "WFS-transaktion: LYCKADES ${response}",
-
-    'commitFailed': "WFS-transaktion: MISSLYCKADES ${response}",
-
-    'googleWarning':
-        "Google-lagret kunde inte laddas korrekt.<br><br>" + 
-        "F�r att slippa detta meddelande, v�lj en annan bakgrundskarta " +
-        "i lagerv�ljaren i �vre h�gra h�rnet.<br><br>" +
-        "Sannolikt beror felet p� att Google Maps-biblioteket " + 
-        "inte �r inkluderat p� webbsidan eller p� att sidan " +
-        "inte anger korrekt API-nyckel f�r webbplatsen.<br><br>" +
-        "Utvecklare: hj�lp f�r att �tg�rda detta, " +
-        "<a href='http://trac.openlayers.org/wiki/Google' " +
-        "target='_blank'>klicka h�r</a>.",
-
-    'getLayerWarning':
-        "${layerType}-lagret kunde inte laddas korrekt.<br><br>" + 
-        "F�r att slippa detta meddelande, v�lj en annan bakgrundskarta " +
-        "i lagerv�ljaren i �vre h�gra h�rnet.<br><br>" +
-        "Sannolikt beror felet p� att ${layerLib}-biblioteket " + 
-        "inte �r inkluderat p� webbsidan.<br><br>" +
-        "Utvecklare: hj�lp f�r att �tg�rda detta, " +
-        "<a href='http://trac.openlayers.org/wiki/${layerLib}' " +
-        "target='_blank'>klicka h�r</a>.",
-
-    'scale': "<strong>Skala</strong> 1 : ${scaleDenom}",
-
-    // console message
-    'layerAlreadyAdded':
-        "Du f�rs�kte l�gga till lagret: ${layerName} p� kartan, men det har lagts till tidigare",
-
-    // console message
-    'reprojectDeprecated':
-        "Du anv�nder inst�llningen 'reproject' p� lagret ${layerName}. " +
-        "Denna inst�llning markerad som deprecated: den var avsedd " +
-        "att anv�ndas f�r att st�dja visning av kartdata p� kommersiella " +
-        "bakgrundskartor, men nu b�r man i st�llet " +
-        "anv�nda Spherical Mercator-st�d f�r den funktionaliteten. " +
-        "Mer information finns " +   
-        "p� http://trac.openlayers.org/wiki/SphericalMercator.",
-
-    // console message
-    'methodDeprecated':
-        "Denna metod �r markerad som deprecated och kommer att tas bort i 3.0. " +
-        "Anv�nd ${newMethod} i st�llet.",
-
-    // console message
-    'boundsAddError': "Du m�ste skicka b�de x- och y-v�rde till funktionen add.",
-
-    // console message
-    'lonlatAddError': "Du m�ste skicka b�de lon- och lat-v�rde till funktionen add.",
-
-    // console message
-    'pixelAddError': "Du m�ste skicka b�de x- och y-v�rde till funktionen add.",
-
-    // console message
-    'unsupportedGeometryType': "St�d saknas f�r geometritypen: ${geomType}",
-
-    // console message
-    'pagePositionFailed':
-        "OpenLayers.Util.pagePosition misslyckades: elementet med id ${elemId} kan placeras fel.",
-                    
-    'end': ''
-};
+/* Translators (2009 onwards):
+ *  - Sannab
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["sv"]
+ * Dictionary for Svenska.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["sv"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Ej hanterad fråga retur ${statusText}",
+
+    'permalink': "Permalänk",
+
+    'overlays': "Kartlager",
+
+    'baseLayer': "Bakgrundskarta",
+
+    'sameProjection': "Översiktskartan fungerar endast när den har samma projektion som huvudkartan",
+
+    'readNotImplemented': "Läsning ej implementerad.",
+
+    'writeNotImplemented': "Skrivning ej implementerad.",
+
+    'noFID': "Kan ej uppdatera feature (objekt) för vilket FID saknas.",
+
+    'errorLoadingGML': "Fel i laddning av GML-fil ${url}",
+
+    'browserNotSupported': "Din webbläsare stöder inte vektorvisning. För närvarande stöds följande visning:\n${renderers}",
+
+    'componentShouldBe': "addFeatures : komponenten skall vara en ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent anropad för lager utan utritning. Detta betyder oftast att man raderat ett lager, men inte en hanterare som är knuten till lagret.",
+
+    'minZoomLevelError': "Egenskapen minZoomLevel är endast avsedd att användas med lager med FixedZoomLevels. Att detta WFS-lager kontrollerar minZoomLevel är en relik från äldre versioner. Vi kan dock inte ta bort det utan att riskera att OL-baserade tillämpningar som använder detta slutar fungera. Därför är det satt som deprecated, minZoomLevel kommer att tas bort i version 3.0. Använd i stället inställning av min/max resolution som beskrivs här: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "WFS-transaktion: LYCKADES ${response}",
+
+    'commitFailed': "WFS-transaktion: MISSLYCKADES ${response}",
+
+    'googleWarning': "Google-lagret kunde inte laddas korrekt.\x3cbr\x3e\x3cbr\x3eFör att slippa detta meddelande, välj en annan bakgrundskarta i lagerväljaren i övre högra hörnet.\x3cbr\x3e\x3cbr\x3eSannolikt beror felet på att Google Maps-biblioteket inte är inkluderat på webbsidan eller på att sidan inte anger korrekt API-nyckel för webbplatsen.\x3cbr\x3e\x3cbr\x3eUtvecklare: hjälp för att åtgärda detta, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklicka här\x3c/a\x3e.",
+
+    'getLayerWarning': "${layerType}-lagret kunde inte laddas korrekt.\x3cbr\x3e\x3cbr\x3eFör att slippa detta meddelande, välj en annan bakgrundskarta i lagerväljaren i övre högra hörnet.\x3cbr\x3e\x3cbr\x3eSannolikt beror felet på att ${layerLib}-biblioteket inte är inkluderat på webbsidan.\x3cbr\x3e\x3cbr\x3eUtvecklare: hjälp för att åtgärda detta, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklicka här\x3c/a\x3e.",
+
+    'scale': "\x3cstrong\x3eSkala\x3c/strong\x3e 1 : ${scaleDenom}",
+
+    'layerAlreadyAdded': "Du försökte lägga till lagret: ${layerName} på kartan, men det har lagts till tidigare",
+
+    'reprojectDeprecated': "Du använder inställningen \'reproject\' på lagret ${layerName}. Denna inställning markerad som deprecated: den var avsedd att användas för att stödja visning av kartdata på kommersiella bakgrundskartor, men nu bör man i stället använda Spherical Mercator-stöd för den funktionaliteten. Mer information finns på http://trac.openlayers.org/wiki/SphericalMercator.",
+
+    'methodDeprecated': "Denna metod är markerad som deprecated och kommer att tas bort i 3.0. Använd ${newMethod} i stället.",
+
+    'boundsAddError': "Du måste skicka både x- och y-värde till funktionen add.",
+
+    'lonlatAddError': "Du måste skicka både lon- och lat-värde till funktionen add.",
+
+    'pixelAddError': "Du måste skicka både x- och y-värde till funktionen add.",
+
+    'unsupportedGeometryType': "Stöd saknas för geometritypen: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition misslyckades: elementet med id ${elemId} kan placeras fel.",
+
+    'filterEvaluateNotImplemented': "evaluering har ej implementerats för denna typ av filter."
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/te.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/te.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/te.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/te.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,27 @@
+/* Translators (2009 onwards):
+ *  - Veeven
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["te"]
+ * Dictionary for తెలుగు.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["te"] = OpenLayers.Util.applyDefaults({
+
+    'permalink': "స్థిరలింకు",
+
+    'W': "à°ª",
+
+    'E': "తూ",
+
+    'N': "à°‰",
+
+    'S': "à°¦"
+
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Lang/vi.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Lang/vi.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/vi.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/vi.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,79 @@
+/* Translators (2009 onwards):
+ *  - Minh Nguyen
+ */
+
+/**
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Namespace: OpenLayers.Lang["vi"]
+ * Dictionary for Tiếng Việt.  Keys for entries are used in calls to
+ *     <OpenLayers.Lang.translate>.  Entry bodies are normal strings or
+ *     strings formatted for use with <OpenLayers.String.format> calls.
+ */
+OpenLayers.Lang["vi"] = OpenLayers.Util.applyDefaults({
+
+    'unhandledRequest': "Không xử lý được phản hồi ${statusText} cho yêu cầu",
+
+    'permalink': "Liên kết thường trực",
+
+    'overlays': "Lấp bản đồ",
+
+    'baseLayer': "Lớp nền",
+
+    'sameProjection': "Bản đồ toàn cảnh chỉ hoạt động khi cùng phép chiếu với bản đồ chính",
+
+    'readNotImplemented': "Chưa hỗ trợ chức năng đọc.",
+
+    'writeNotImplemented': "Chưa hỗ trợ chức năng viết.",
+
+    'noFID': "Không thể cập nhật tính năng thiếu FID.",
+
+    'errorLoadingGML': "Lỗi tải tập tin GML tại ${url}",
+
+    'browserNotSupported': "Trình duyệt của bạn không hỗ trợ chức năng vẽ bằng vectơ. Hiện hỗ trợ các bộ kết xuất:\n${renderers}",
+
+    'componentShouldBe': "addFeatures: bộ phận cần phải là ${geomType}",
+
+    'getFeatureError': "getFeatureFromEvent được gọi từ lớp không có bộ kết xuất. Thường thì có lẽ lớp bị xóa nhưng một phần xử lý của nó vẫn còn.",
+
+    'minZoomLevelError': "Chỉ nên sử dụng thuộc tính minZoomLevel với các lớp FixedZoomLevels-descendent. Việc lớp wfs này tìm cho minZoomLevel là di tích còn lại từ xưa. Tuy nhiên, nếu chúng tôi dời nó thì sẽ vỡ các chương trình OpenLayers mà dựa trên nó. Bởi vậy chúng tôi phản đối sử dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dời vào phiên bản 3.0. Xin sử dụng thiết lập độ phân tích tối thiểu / tối đa thay thế, theo hướng dẫn này: http://trac.openlayers.org/wiki/SettingZoomLevels",
+
+    'commitSuccess': "Giao dịch WFS: THÀNH CÔNG ${response}",
+
+    'commitFailed': "Giao dịch WFS: THẤT BẠI ${response}",
+
+    'googleWarning': "Không thể tải lớp Google đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp với website của bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",
+
+    'getLayerWarning': "Không thể tải lớp ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",
+
+    'scale': "Tỷ lệ = 1 : ${scaleDenom}",
+
+    'W': "T",
+
+    'E': "Đ",
+
+    'N': "B",
+
+    'S': "N",
+
+    'layerAlreadyAdded': "Bạn muốn thêm lớp ${layerName} vào bản đồ, nhưng lớp này đã được thêm",
+
+    'reprojectDeprecated': "Bạn đang áp dụng chế độ “reproject” vào lớp ${layerName}. Chế độ này đã bị phản đối: nó có mục đích hỗ trợ lấp dữ liệu trên các nền bản đồ thương mại; nên thực hiện hiệu ứng đó dùng tính năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",
+
+    'methodDeprecated': "Phương thức này đã bị phản đối và sẽ bị dời vào phiên bản 3.0. Xin hãy sử dụng ${newMethod} thay thế.",
+
+    'boundsAddError': "Cần phải cho cả giá trị x và y vào hàm add.",
+
+    'lonlatAddError': "Cần phải cho cả giá trị lon và lat vào hàm add.",
+
+    'pixelAddError': "Cần phải cho cả giá trị x và y vào hàm add.",
+
+    'unsupportedGeometryType': "Không hỗ trợ kiểu địa lý: ${geomType}",
+
+    'pagePositionFailed': "OpenLayers.Util.pagePosition bị thất bại: nguyên tố với ID ${elemId} có thể ở chỗ sai.",
+
+    'filterEvaluateNotImplemented': "chưa hỗ trợ evaluate cho loại bộ lọc này."
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-CN.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-CN.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-CN.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-TW.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-TW.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang/zh-TW.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,3 @@
-/* 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. */
-
 /**
  * @requires OpenLayers/Lang.js
  */

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Lang.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Lang.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Lang.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -57,7 +58,7 @@
     setCode: function(code) {
         var lang;
         if(!code) {
-            code = (OpenLayers.Util.getBrowserName() == "msie") ?
+            code = (OpenLayers.BROWSER_NAME == "msie") ?
                 navigator.userLanguage : navigator.language;
         }
         var parts = code.split('-');

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcGIS93Rest.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcGIS93Rest.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcGIS93Rest.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2008 Avencia, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -45,7 +46,7 @@
      * Example:
      * (code)
      * var arcims = new OpenLayers.Layer.ArcGIS93Rest("MyName",
-     *                                    "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer", 
+     *                                    "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/export", 
      *                                    {
      *                                      layers: "0,1,2"
      *                                    });
@@ -113,7 +114,7 @@
             obj = new OpenLayers.Layer.ArcGIS93Rest(this.name,
                                            this.url,
                                            this.params,
-                                           this.options);
+                                           this.getOptions());
         }
 
         //get all additions from superclasses

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcIMS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcIMS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/ArcIMS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 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. */ 
+/* 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/Layer/Grid.js
@@ -420,6 +421,29 @@
             }
         });
     },
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.ArcIMS>} An exact clone of this layer
+     */
+    clone: function (obj) {
+
+        if (obj == null) {
+            obj = new OpenLayers.Layer.ArcIMS(this.name,
+                                           this.url,
+                                           this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
     
     /**
      * Method: addTile

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Boxes.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Boxes.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Boxes.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/EventPane.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/EventPane.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/EventPane.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -80,6 +81,7 @@
      */
     destroy: function() {
         this.mapObject = null;
+        this.pane = null;
         OpenLayers.Layer.prototype.destroy.apply(this, arguments); 
     },
 
@@ -100,7 +102,7 @@
         this.pane.style.display = this.div.style.display;
         this.pane.style.width="100%";
         this.pane.style.height="100%";
-        if (OpenLayers.Util.getBrowserName() == "msie") {
+        if (OpenLayers.BROWSER_NAME == "msie") {
             this.pane.style.background = 
                 "url(" + OpenLayers.Util.getImagesLocation() + "blank.gif)";
         }
@@ -131,7 +133,6 @@
     removeMap: function(map) {
         if (this.pane && this.pane.parentNode) {
             this.pane.parentNode.removeChild(this.pane);
-            this.pane = null;
         }
         OpenLayers.Layer.prototype.removeMap.apply(this, arguments);
     },

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/FixedZoomLevels.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/FixedZoomLevels.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/FixedZoomLevels.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/GML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/GML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/GML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -12,6 +13,9 @@
  * Class: OpenLayers.Layer.GML
  * Create a vector layer by parsing a GML file. The GML file is
  *     passed in as a parameter.
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.Vector
+ *     with Protocol.HTTP and Strategy.Fixed. Provide the protocol with a 
+ *     format parameter to get the parser you want for your data.
  *
  * Inherits from:
  *  - <OpenLayers.Layer.Vector>
@@ -128,7 +132,7 @@
     /**
      * Method: requestSuccess
      * Process GML after it has been loaded.
-     * Called by initialise() and loadUrl() after the GML has been loaded.
+     * Called by initialize() and loadUrl() after the GML has been loaded.
      *
      * Parameters:
      * request - {String} 
@@ -156,7 +160,7 @@
     /**
      * Method: requestFailure
      * Process a failed loading of GML.
-     * Called by initialise() and loadUrl() if there was a problem loading GML.
+     * Called by initialize() and loadUrl() if there was a problem loading GML.
      *
      * Parameters:
      * request - {String} 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/GeoRSS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/GeoRSS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/GeoRSS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/Google/v3.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,420 +0,0 @@
-/* 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/Layer/Google.js
- */
-
-/**
- * Constant: OpenLayers.Layer.Google.v3
- * 
- * Mixin providing functionality specific to the Google Maps API v3. Note that
- * this layer configures the google.maps.map object with the "disableDefaultUI"
- * option set to true. Using UI controls that the Google Maps API provides is
- * not supported by the OpenLayers API.
- */
-OpenLayers.Layer.Google.v3 = {
-    
-    /**
-     * Constant: DEFAULTS
-     * {Object} It is not recommended to change the properties set here. Note
-     * that Google.v3 layers only work when sphericalMercator is set to true.
-     * 
-     * (code)
-     * {
-     *     maxExtent: new OpenLayers.Bounds(
-     *         -128 * 156543.0339,
-     *         -128 * 156543.0339,
-     *         128 * 156543.0339,
-     *         128 * 156543.0339
-     *     ),
-     *     sphericalMercator: true,
-     *     maxResolution: 156543.0339,
-     *     units: "m",
-     *     projection: "EPSG:900913"
-     * }
-     * (end)
-     */
-    DEFAULTS: {
-        maxExtent: new OpenLayers.Bounds(
-            -128 * 156543.0339,
-            -128 * 156543.0339,
-            128 * 156543.0339,
-            128 * 156543.0339
-        ),
-        sphericalMercator: true,
-        maxResolution: 156543.0339,
-        units: "m",
-        projection: "EPSG:900913"
-    },
-
-    /** 
-     * Method: loadMapObject
-     * Load the GMap and register appropriate event listeners. If we can't 
-     *     load GMap2, then display a warning message.
-     */
-    loadMapObject:function() {
-        if (!this.type) {
-            this.type = google.maps.MapTypeId.ROADMAP;
-        }
-        var mapObject;
-        var cache = OpenLayers.Layer.Google.cache[this.map.id];
-        if (cache) {
-            // there are already Google layers added to this map
-            mapObject = cache.mapObject;
-            // increment the layer count
-            ++cache.count;
-        } else {
-            // this is the first Google layer for this map
-
-            var container = this.map.viewPortDiv;
-            var div = document.createElement("div");
-            div.id = this.map.id + "_GMapContainer";
-            div.style.position = "absolute";
-            div.style.width = "100%";
-            div.style.height = "100%";
-            container.appendChild(div);
-
-            // create GMap and shuffle elements
-            var center = this.map.getCenter();
-            mapObject = new google.maps.Map(div, {
-                center: center ?
-                    new google.maps.LatLng(center.lat, center.lon) :
-                    new google.maps.LatLng(0, 0),
-                zoom: this.map.getZoom() || 0,
-                mapTypeId: this.type,
-                disableDefaultUI: true,
-                keyboardShortcuts: false,
-                draggable: false,
-                disableDoubleClickZoom: true,
-                scrollwheel: false,
-                streetViewControl: false
-            });
-            
-            // cache elements for use by any other google layers added to
-            // this same map
-            cache = {
-                mapObject: mapObject,
-                count: 1
-            };
-            OpenLayers.Layer.Google.cache[this.map.id] = cache;
-            this.repositionListener = google.maps.event.addListenerOnce(
-                mapObject, 
-                "center_changed", 
-                OpenLayers.Function.bind(this.repositionMapElements, this)
-            );
-        }
-        this.mapObject = mapObject;
-        this.setGMapVisibility(this.visibility);
-    },
-    
-    /**
-     * Method: repositionMapElements
-     *
-     * Waits until powered by and terms of use elements are available and then
-     * moves them so they are clickable.
-     */
-    repositionMapElements: function() {
-
-        // This is the first time any Google layer in this mapObject has been
-        // made visible.  The mapObject needs to know the container size.
-        google.maps.event.trigger(this.mapObject, "resize");
-        
-        var div = this.mapObject.getDiv().firstChild;
-        if (!div || div.childNodes.length < 3) {
-            this.repositionTimer = window.setTimeout(
-                OpenLayers.Function.bind(this.repositionMapElements, this),
-                250
-            );
-            return false;
-        }
-
-        var cache = OpenLayers.Layer.Google.cache[this.map.id];
-        var container = this.map.viewPortDiv;
-
-        // move the ToS and branding stuff up to the container div
-        var termsOfUse = div.lastChild;
-        container.appendChild(termsOfUse);
-        termsOfUse.style.zIndex = "1100";
-        termsOfUse.style.bottom = "";
-        termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
-        termsOfUse.style.display = "";
-        cache.termsOfUse = termsOfUse;
-
-        var poweredBy = div.lastChild;
-        container.appendChild(poweredBy);
-        poweredBy.style.zIndex = "1100";
-        poweredBy.style.bottom = "";
-        poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
-        poweredBy.style.display = "";
-        cache.poweredBy = poweredBy;
-
-        this.setGMapVisibility(this.visibility);
-
-    },
-
-    /**
-     * APIMethod: onMapResize
-     */
-    onMapResize: function() {
-        if (this.visibility) {
-            google.maps.event.trigger(this.mapObject, "resize");
-        } else {
-            if (!this._resized) {
-                var layer = this;
-                google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() {
-                    delete layer._resized;
-                    google.maps.event.trigger(layer.mapObject, "resize");
-                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
-                });
-            }
-            this._resized = true;
-        }
-    },
-
-    /**
-     * Method: setGMapVisibility
-     * Display the GMap container and associated elements.
-     * 
-     * Parameters:
-     * visible - {Boolean} Display the GMap elements.
-     */
-    setGMapVisibility: function(visible) {
-        var cache = OpenLayers.Layer.Google.cache[this.map.id];
-        if (cache) {
-            var type = this.type;
-            var layers = this.map.layers;
-            var layer;
-            for (var i=layers.length-1; i>=0; --i) {
-                layer = layers[i];
-                if (layer instanceof OpenLayers.Layer.Google &&
-                            layer.visibility === true && layer.inRange === true) {
-                    type = layer.type;
-                    visible = true;
-                    break;
-                }
-            }
-            var container = this.mapObject.getDiv();
-            if (visible === true) {
-                this.mapObject.setMapTypeId(type);                
-                container.style.left = "";
-                if (cache.termsOfUse && cache.termsOfUse.style) {
-                    cache.termsOfUse.style.left = "";
-                    cache.termsOfUse.style.display = "";
-                    cache.poweredBy.style.display = "";            
-                }
-                cache.displayed = this.id;
-            } else {
-                delete cache.displayed;
-                container.style.left = "-9999px";
-                if (cache.termsOfUse && cache.termsOfUse.style) {
-                    cache.termsOfUse.style.display = "none";
-                    // move ToU far to the left in addition to setting
-                    // display to "none", because at the end of the GMap
-                    // load sequence, display: none will be unset and ToU
-                    // would be visible after loading a map with a google
-                    // layer that is initially hidden. 
-                    cache.termsOfUse.style.left = "-9999px";
-                    cache.poweredBy.style.display = "none";
-                }
-            }
-        }
-    },
-    
-    /**
-     * Method: getMapContainer
-     * 
-     * Returns:
-     * {DOMElement} the GMap container's div
-     */
-    getMapContainer: function() {
-        return this.mapObject.getDiv();
-    },
-    
-  //
-  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
-  //
-
-    /**
-     * APIMethod: getMapObjectBoundsFromOLBounds
-     * 
-     * Parameters:
-     * olBounds - {<OpenLayers.Bounds>}
-     * 
-     * Returns:
-     * {Object} A MapObject Bounds, translated from olBounds
-     *          Returns null if null value is passed in
-     */
-    getMapObjectBoundsFromOLBounds: function(olBounds) {
-        var moBounds = null;
-        if (olBounds != null) {
-            var sw = this.sphericalMercator ? 
-              this.inverseMercator(olBounds.bottom, olBounds.left) : 
-              new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
-            var ne = this.sphericalMercator ? 
-              this.inverseMercator(olBounds.top, olBounds.right) : 
-              new OpenLayers.LonLat(olBounds.top, olBounds.right);
-            moBounds = new google.maps.LatLngBounds(
-                new google.maps.LatLng(sw.lat, sw.lon),
-                new google.maps.LatLng(ne.lat, ne.lon)
-            );
-        }
-        return moBounds;
-    },
-
-
-    /************************************
-     *                                  *
-     *   MapObject Interface Controls   *
-     *                                  *
-     ************************************/
-
-
-  // LonLat - Pixel Translation
-  
-    /**
-     * APIMethod: getMapObjectLonLatFromMapObjectPixel
-     * 
-     * Parameters:
-     * moPixel - {Object} MapObject Pixel format
-     * 
-     * Returns:
-     * {Object} MapObject LonLat translated from MapObject Pixel
-     */
-    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
-        var size = this.map.getSize();
-        var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center);
-        var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center);
-        var res = this.map.getResolution();
-
-        var delta_x = moPixel.x - (size.w / 2);
-        var delta_y = moPixel.y - (size.h / 2);
-    
-        var lonlat = new OpenLayers.LonLat(
-            lon + delta_x * res,
-            lat - delta_y * res
-        ); 
-
-        if (this.wrapDateLine) {
-            lonlat = lonlat.wrapDateLine(this.maxExtent);
-        }
-        return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat);
-    },
-
-    /**
-     * APIMethod: getMapObjectPixelFromMapObjectLonLat
-     * 
-     * Parameters:
-     * moLonLat - {Object} MapObject LonLat format
-     * 
-     * Returns:
-     * {Object} MapObject Pixel transtlated from MapObject LonLat
-     */
-    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
-        var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
-        var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
-        var res = this.map.getResolution();
-        var extent = this.map.getExtent();
-        var px = new OpenLayers.Pixel(
-            (1/res * (lon - extent.left)),
-            (1/res * (extent.top - lat))
-        );    
-        return this.getMapObjectPixelFromXY(px.x, px.y);
-    },
-
-  
-    /** 
-     * APIMethod: setMapObjectCenter
-     * Set the mapObject to the specified center and zoom
-     * 
-     * Parameters:
-     * center - {Object} MapObject LonLat format
-     * zoom - {int} MapObject zoom format
-     */
-    setMapObjectCenter: function(center, zoom) {
-        this.mapObject.setOptions({
-            center: center,
-            zoom: zoom
-        });
-    },
-   
-    
-  // Bounds
-  
-    /** 
-     * APIMethod: getMapObjectZoomFromMapObjectBounds
-     * 
-     * Parameters:
-     * moBounds - {Object} MapObject Bounds format
-     * 
-     * Returns:
-     * {Object} MapObject Zoom for specified MapObject Bounds
-     */
-    getMapObjectZoomFromMapObjectBounds: function(moBounds) {
-        return this.mapObject.getBoundsZoomLevel(moBounds);
-    },
-
-    /************************************
-     *                                  *
-     *       MapObject Primitives       *
-     *                                  *
-     ************************************/
-
-
-  // LonLat
-    
-    /**
-     * APIMethod: getMapObjectLonLatFromLonLat
-     * 
-     * Parameters:
-     * lon - {Float}
-     * lat - {Float}
-     * 
-     * Returns:
-     * {Object} MapObject LonLat built from lon and lat params
-     */
-    getMapObjectLonLatFromLonLat: function(lon, lat) {
-        var gLatLng;
-        if(this.sphericalMercator) {
-            var lonlat = this.inverseMercator(lon, lat);
-            gLatLng = new google.maps.LatLng(lonlat.lat, lonlat.lon);
-        } else {
-            gLatLng = new google.maps.LatLng(lat, lon);
-        }
-        return gLatLng;
-    },
-    
-  // Pixel
-    
-    /**
-     * APIMethod: getMapObjectPixelFromXY
-     * 
-     * Parameters:
-     * x - {Integer}
-     * y - {Integer}
-     * 
-     * Returns:
-     * {Object} MapObject Pixel from x and y parameters
-     */
-    getMapObjectPixelFromXY: function(x, y) {
-        return new google.maps.Point(x, y);
-    },
-        
-    /**
-     * APIMethod: destroy
-     * Clean up this layer.
-     */
-    destroy: function() {
-        if (this.repositionListener) {
-            google.maps.event.removeListener(this.repositionListener);
-        }
-        if (this.repositionTimer) {
-            window.clearTimeout(this.repositionTimer);
-        }
-        OpenLayers.Layer.Google.prototype.destroy.apply(this, arguments);
-    }
-    
-};

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Layer/Google/v3.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google/v3.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,420 @@
+/* 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/Layer/Google.js
+ */
+
+/**
+ * Constant: OpenLayers.Layer.Google.v3
+ * 
+ * Mixin providing functionality specific to the Google Maps API v3. Note that
+ * this layer configures the google.maps.map object with the "disableDefaultUI"
+ * option set to true. Using UI controls that the Google Maps API provides is
+ * not supported by the OpenLayers API.
+ */
+OpenLayers.Layer.Google.v3 = {
+    
+    /**
+     * Constant: DEFAULTS
+     * {Object} It is not recommended to change the properties set here. Note
+     * that Google.v3 layers only work when sphericalMercator is set to true.
+     * 
+     * (code)
+     * {
+     *     maxExtent: new OpenLayers.Bounds(
+     *         -128 * 156543.0339,
+     *         -128 * 156543.0339,
+     *         128 * 156543.0339,
+     *         128 * 156543.0339
+     *     ),
+     *     sphericalMercator: true,
+     *     maxResolution: 156543.0339,
+     *     units: "m",
+     *     projection: "EPSG:900913"
+     * }
+     * (end)
+     */
+    DEFAULTS: {
+        maxExtent: new OpenLayers.Bounds(
+            -128 * 156543.0339,
+            -128 * 156543.0339,
+            128 * 156543.0339,
+            128 * 156543.0339
+        ),
+        sphericalMercator: true,
+        maxResolution: 156543.0339,
+        units: "m",
+        projection: "EPSG:900913"
+    },
+
+    /** 
+     * Method: loadMapObject
+     * Load the GMap and register appropriate event listeners. If we can't 
+     *     load GMap2, then display a warning message.
+     */
+    loadMapObject:function() {
+        if (!this.type) {
+            this.type = google.maps.MapTypeId.ROADMAP;
+        }
+        var mapObject;
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // there are already Google layers added to this map
+            mapObject = cache.mapObject;
+            // increment the layer count
+            ++cache.count;
+        } else {
+            // this is the first Google layer for this map
+
+            var container = this.map.viewPortDiv;
+            var div = document.createElement("div");
+            div.id = this.map.id + "_GMapContainer";
+            div.style.position = "absolute";
+            div.style.width = "100%";
+            div.style.height = "100%";
+            container.appendChild(div);
+
+            // create GMap and shuffle elements
+            var center = this.map.getCenter();
+            mapObject = new google.maps.Map(div, {
+                center: center ?
+                    new google.maps.LatLng(center.lat, center.lon) :
+                    new google.maps.LatLng(0, 0),
+                zoom: this.map.getZoom() || 0,
+                mapTypeId: this.type,
+                disableDefaultUI: true,
+                keyboardShortcuts: false,
+                draggable: false,
+                disableDoubleClickZoom: true,
+                scrollwheel: false,
+                streetViewControl: false
+            });
+            
+            // cache elements for use by any other google layers added to
+            // this same map
+            cache = {
+                mapObject: mapObject,
+                count: 1
+            };
+            OpenLayers.Layer.Google.cache[this.map.id] = cache;
+            this.repositionListener = google.maps.event.addListenerOnce(
+                mapObject, 
+                "center_changed", 
+                OpenLayers.Function.bind(this.repositionMapElements, this)
+            );
+        }
+        this.mapObject = mapObject;
+        this.setGMapVisibility(this.visibility);
+    },
+    
+    /**
+     * Method: repositionMapElements
+     *
+     * Waits until powered by and terms of use elements are available and then
+     * moves them so they are clickable.
+     */
+    repositionMapElements: function() {
+
+        // This is the first time any Google layer in this mapObject has been
+        // made visible.  The mapObject needs to know the container size.
+        google.maps.event.trigger(this.mapObject, "resize");
+        
+        var div = this.mapObject.getDiv().firstChild;
+        if (!div || div.childNodes.length < 3) {
+            this.repositionTimer = window.setTimeout(
+                OpenLayers.Function.bind(this.repositionMapElements, this),
+                250
+            );
+            return false;
+        }
+
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        var container = this.map.viewPortDiv;
+
+        // move the ToS and branding stuff up to the container div
+        var termsOfUse = div.lastChild;
+        container.appendChild(termsOfUse);
+        termsOfUse.style.zIndex = "1100";
+        termsOfUse.style.bottom = "";
+        termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
+        termsOfUse.style.display = "";
+        cache.termsOfUse = termsOfUse;
+
+        var poweredBy = div.lastChild;
+        container.appendChild(poweredBy);
+        poweredBy.style.zIndex = "1100";
+        poweredBy.style.bottom = "";
+        poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
+        poweredBy.style.display = "";
+        cache.poweredBy = poweredBy;
+
+        this.setGMapVisibility(this.visibility);
+
+    },
+
+    /**
+     * APIMethod: onMapResize
+     */
+    onMapResize: function() {
+        if (this.visibility) {
+            google.maps.event.trigger(this.mapObject, "resize");
+        } else {
+            if (!this._resized) {
+                var layer = this;
+                google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() {
+                    delete layer._resized;
+                    google.maps.event.trigger(layer.mapObject, "resize");
+                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
+                });
+            }
+            this._resized = true;
+        }
+    },
+
+    /**
+     * Method: setGMapVisibility
+     * Display the GMap container and associated elements.
+     * 
+     * Parameters:
+     * visible - {Boolean} Display the GMap elements.
+     */
+    setGMapVisibility: function(visible) {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            var type = this.type;
+            var layers = this.map.layers;
+            var layer;
+            for (var i=layers.length-1; i>=0; --i) {
+                layer = layers[i];
+                if (layer instanceof OpenLayers.Layer.Google &&
+                            layer.visibility === true && layer.inRange === true) {
+                    type = layer.type;
+                    visible = true;
+                    break;
+                }
+            }
+            var container = this.mapObject.getDiv();
+            if (visible === true) {
+                this.mapObject.setMapTypeId(type);                
+                container.style.left = "";
+                if (cache.termsOfUse && cache.termsOfUse.style) {
+                    cache.termsOfUse.style.left = "";
+                    cache.termsOfUse.style.display = "";
+                    cache.poweredBy.style.display = "";            
+                }
+                cache.displayed = this.id;
+            } else {
+                delete cache.displayed;
+                container.style.left = "-9999px";
+                if (cache.termsOfUse && cache.termsOfUse.style) {
+                    cache.termsOfUse.style.display = "none";
+                    // move ToU far to the left in addition to setting
+                    // display to "none", because at the end of the GMap
+                    // load sequence, display: none will be unset and ToU
+                    // would be visible after loading a map with a google
+                    // layer that is initially hidden. 
+                    cache.termsOfUse.style.left = "-9999px";
+                    cache.poweredBy.style.display = "none";
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: getMapContainer
+     * 
+     * Returns:
+     * {DOMElement} the GMap container's div
+     */
+    getMapContainer: function() {
+        return this.mapObject.getDiv();
+    },
+    
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
+     * APIMethod: getMapObjectBoundsFromOLBounds
+     * 
+     * Parameters:
+     * olBounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {Object} A MapObject Bounds, translated from olBounds
+     *          Returns null if null value is passed in
+     */
+    getMapObjectBoundsFromOLBounds: function(olBounds) {
+        var moBounds = null;
+        if (olBounds != null) {
+            var sw = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.bottom, olBounds.left) : 
+              new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
+            var ne = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.top, olBounds.right) : 
+              new OpenLayers.LonLat(olBounds.top, olBounds.right);
+            moBounds = new google.maps.LatLngBounds(
+                new google.maps.LatLng(sw.lat, sw.lon),
+                new google.maps.LatLng(ne.lat, ne.lon)
+            );
+        }
+        return moBounds;
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        var size = this.map.getSize();
+        var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center);
+        var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center);
+        var res = this.map.getResolution();
+
+        var delta_x = moPixel.x - (size.w / 2);
+        var delta_y = moPixel.y - (size.h / 2);
+    
+        var lonlat = new OpenLayers.LonLat(
+            lon + delta_x * res,
+            lat - delta_y * res
+        ); 
+
+        if (this.wrapDateLine) {
+            lonlat = lonlat.wrapDateLine(this.maxExtent);
+        }
+        return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
+        var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
+        var res = this.map.getResolution();
+        var extent = this.map.getExtent();
+        var px = new OpenLayers.Pixel(
+            (1/res * (lon - extent.left)),
+            (1/res * (extent.top - lat))
+        );    
+        return this.getMapObjectPixelFromXY(px.x, px.y);
+    },
+
+  
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.setOptions({
+            center: center,
+            zoom: zoom
+        });
+    },
+   
+    
+  // Bounds
+  
+    /** 
+     * APIMethod: getMapObjectZoomFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object} MapObject Bounds format
+     * 
+     * Returns:
+     * {Object} MapObject Zoom for specified MapObject Bounds
+     */
+    getMapObjectZoomFromMapObjectBounds: function(moBounds) {
+        return this.mapObject.getBoundsZoomLevel(moBounds);
+    },
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var gLatLng;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            gLatLng = new google.maps.LatLng(lonlat.lat, lonlat.lon);
+        } else {
+            gLatLng = new google.maps.LatLng(lat, lon);
+        }
+        return gLatLng;
+    },
+    
+  // Pixel
+    
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new google.maps.Point(x, y);
+    },
+        
+    /**
+     * APIMethod: destroy
+     * Clean up this layer.
+     */
+    destroy: function() {
+        if (this.repositionListener) {
+            google.maps.event.removeListener(this.repositionListener);
+        }
+        if (this.repositionTimer) {
+            window.clearTimeout(this.repositionTimer);
+        }
+        OpenLayers.Layer.Google.prototype.destroy.apply(this, arguments);
+    }
+    
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Google.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -7,7 +8,6 @@
  * @requires OpenLayers/Layer/SphericalMercator.js
  * @requires OpenLayers/Layer/EventPane.js
  * @requires OpenLayers/Layer/FixedZoomLevels.js
- * @requires OpenLayers/Console.js
  */
 
 /**
@@ -30,9 +30,9 @@
     
     /** 
      * Constant: MAX_ZOOM_LEVEL
-     * {Integer} 19
+     * {Integer} 21
      */
-    MAX_ZOOM_LEVEL: 19,
+    MAX_ZOOM_LEVEL: 21,
 
     /** 
      * Constant: RESOLUTIONS
@@ -59,7 +59,9 @@
         0.00002145767211914062, 
         0.00001072883605957031,
         0.00000536441802978515, 
-        0.00000268220901489257
+        0.00000268220901489257,
+        0.0000013411045074462891,
+        0.00000067055225372314453
     ],
 
     /**
@@ -69,6 +71,14 @@
     type: null,
 
     /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
      * APIProperty: sphericalMercator
      * {Boolean} Should the map act as a mercator-projected map? This will
      *     cause all interactions with the map to be in the actual map 
@@ -78,24 +88,11 @@
     sphericalMercator: false, 
     
     /**
-     * Property: dragObject
-     * {GDraggableObject} Since 2.93, Google has exposed the ability to get
-     *     the maps GDraggableObject. We can now use this for smooth panning
+     * Property: version
+     * {Number} The version of the Google Maps API
      */
-    dragObject: null, 
+    version: null,
 
-    /**
-     * Property: termsOfUse
-     * {DOMElement} Div for Google's copyright and terms of use link
-     */
-    termsOfUse: null, 
-
-    /**
-     * Property: poweredBy
-     * {DOMElement} Div for Google's powered by logo and link
-     */
-    poweredBy: null, 
-
     /** 
      * Constructor: OpenLayers.Layer.Google
      * 
@@ -105,146 +102,174 @@
      *     on the layer.
      */
     initialize: function(name, options) {
-        OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
+        options = options || {};
+        if(!options.version) {
+            options.version = typeof GMap2 === "function" ? "2" : "3";
+        }
+        var mixin = OpenLayers.Layer.Google["v" +
+            options.version.replace(/\./g, "_")];
+        if (mixin) {
+            OpenLayers.Util.applyDefaults(options, mixin);
+        } else {
+            throw "Unsupported Google Maps API version: " + options.version;
+        }
+
+        OpenLayers.Util.applyDefaults(options, mixin.DEFAULTS);
+        if (options.maxExtent) {
+            options.maxExtent = options.maxExtent.clone();
+        }
+
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this,
+            [name, options]);
         OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
-                                                                    arguments);
-        this.addContainerPxFunction();
+            [name, options]);
+
         if (this.sphericalMercator) {
             OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
             this.initMercatorParameters();
         }    
     },
-    
-    /** 
-     * Method: loadMapObject
-     * Load the GMap and register appropriate event listeners. If we can't 
-     *     load GMap2, then display a warning message.
+
+    /**
+     * Method: clone
+     * Create a clone of this layer
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Google>} An exact clone of this layer
      */
-    loadMapObject:function() {
-        
-        //has gmaps library has been loaded?
-        try {
-            // create GMap, hide nav controls
-            this.mapObject = new GMap2( this.div );
-            
-            //since v 2.93 getDragObject is now available.
-            if(typeof this.mapObject.getDragObject == "function") {
-                this.dragObject = this.mapObject.getDragObject();
-            } else {
-                this.dragPanMapObject = null;
-            }
-
-            // move the ToS and branding stuff up to the container div
-            this.termsOfUse = this.div.lastChild;
-            this.div.removeChild(this.termsOfUse);
-            if (this.isFixed) {
-                this.map.viewPortDiv.appendChild(this.termsOfUse);
-            } else {
-                this.map.layerContainerDiv.appendChild(this.termsOfUse);
-            }
-            this.termsOfUse.style.zIndex = "1100";
-            this.termsOfUse.style.display = this.div.style.display;
-            this.termsOfUse.style.right = "";
-            this.termsOfUse.style.bottom = "";
-            this.termsOfUse.className = "olLayerGoogleCopyright";
-
-            this.poweredBy = this.div.lastChild;
-            this.div.removeChild(this.poweredBy);
-            if (this.isFixed) {
-                this.map.viewPortDiv.appendChild(this.poweredBy);
-            } else {
-                this.map.layerContainerDiv.appendChild(this.poweredBy);
-            }
-            this.poweredBy.style.zIndex = "1100";
-            this.poweredBy.style.display = this.div.style.display;
-            this.poweredBy.style.right = "";
-            this.poweredBy.style.bottom = "";
-            this.poweredBy.className = "olLayerGooglePoweredBy gmnoprint"; 
-
-        } catch (e) {
-            OpenLayers.Console.error(e);
-        }
-               
+    clone: function() {
+        /**
+         * This method isn't intended to be called by a subclass and it
+         * doesn't call the same method on the superclass.  We don't call
+         * the super's clone because we don't want properties that are set
+         * on this layer after initialize (i.e. this.mapObject etc.).
+         */
+        return new OpenLayers.Layer.Google(
+            this.name, this.getOptions()
+        );
     },
 
-    /** 
-     * APIMethod: setMap
-     * Overridden from EventPane because if a map type has been specified, 
-     *     we need to attach a listener for the first moveend -- this is how 
-     *     we will know that the map has been centered. Only once the map has 
-     *     been centered is it safe to change the gmap object's map type. 
+    /**
+     * APIMethod: setVisibility
+     * Set the visibility flag for the layer and hide/show & redraw 
+     *     accordingly. Fire event unless otherwise specified
      * 
+     * Note that visibility is no longer simply whether or not the layer's
+     *     style.display is set to "block". Now we store a 'visibility' state 
+     *     property on the layer class, this allows us to remember whether or 
+     *     not we *desire* for a layer to be visible. In the case where the 
+     *     map's resolution is out of the layer's range, this desire may be 
+     *     subverted.
+     * 
      * Parameters:
-     * map - {<OpenLayers.Map>}
+     * visible - {Boolean} Display the layer (if in range)
      */
-    setMap: function(map) {
-        OpenLayers.Layer.EventPane.prototype.setMap.apply(this, arguments);
-
-        if (this.type != null) {
-            this.map.events.register("moveend", this, this.setMapType);
-        }
+    setVisibility: function(visible) {
+        // sharing a map container, opacity has to be set per layer
+        var opacity = this.opacity == null ? 1 : this.opacity;
+        OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this, arguments);
+        this.setOpacity(opacity);
     },
     
     /** 
-     * Method: setMapType
-     * The map has been centered, and a map type was specified, so we 
-     *     set the map type on the gmap object, then unregister the listener
-     *     so that we dont keep doing this every time the map moves.
+     * APIMethod: display
+     * Hide or show the Layer
+     * 
+     * Parameters:
+     * display - {Boolean}
      */
-    setMapType: function() {
-        if (this.mapObject.getCenter() != null) {
-            
-            // Support for custom map types.
-            if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
-                                        this.type) == -1) {
-                this.mapObject.addMapType(this.type);
-            }    
-
-            this.mapObject.setMapType(this.type);
-            this.map.events.unregister("moveend", this, this.setMapType);
+    display: function(visible) {
+        if (!this._dragging) {
+            this.setGMapVisibility(visible);
         }
+        OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments);
     },
-
+    
     /**
-     * APIMethod: onMapResize
+     * Method: moveTo
      * 
      * Parameters:
-     * evt - {Event}
+     * bound - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to
+     *     do some init work in that case.
+     * dragging - {Boolean}
      */
-    onMapResize: function() {
-        // workaround for resizing of invisible or not yet fully loaded layers
-        // where GMap2.checkResize() does not work. We need to load the GMap
-        // for the old div size, then checkResize(), and then call
-        // layer.moveTo() to trigger GMap.setCenter() (which will finish
-        // the GMap initialization).
-        if(this.visibility && this.mapObject.isLoaded()) {
-            this.mapObject.checkResize();
-        } else {
-            if(!this._resized) {
-                var layer = this;
-                var handle = GEvent.addListener(this.mapObject, "load", function() {
-                    GEvent.removeListener(handle);
-                    delete layer._resized;
-                    layer.mapObject.checkResize();
-                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
-                })
+    moveTo: function(bounds, zoomChanged, dragging) {
+        this._dragging = dragging;
+        OpenLayers.Layer.EventPane.prototype.moveTo.apply(this, arguments);
+        delete this._dragging;
+    },
+    
+    /**
+     * APIMethod: setOpacity
+     * Sets the opacity for the entire layer (all images)
+     * 
+     * Parameter:
+     * opacity - {Float}
+     */
+    setOpacity: function(opacity) {
+        if (opacity !== this.opacity) {
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "opacity"
+                });
             }
-            this._resized = true;
+            this.opacity = opacity;
         }
+        // Though this layer's opacity may not change, we're sharing a container
+        // and need to update the opacity for the entire container.
+        if (this.getVisibility()) {
+            var container = this.getMapContainer();
+            OpenLayers.Util.modifyDOMElement(
+                container, null, null, null, null, null, null, opacity
+            );
+        }
     },
 
     /**
-     * Method: display
-     * Hide or show the layer
-     *
-     * Parameters:
-     * display - {Boolean}
+     * APIMethod: destroy
+     * Clean up this layer.
      */
-    display: function(display) {
-        OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments);
-        this.termsOfUse.style.display = this.div.style.display;
-        this.poweredBy.style.display = this.div.style.display;
+    destroy: function() {
+        /**
+         * We have to override this method because the event pane destroy
+         * deletes the mapObject reference before removing this layer from
+         * the map.
+         */
+        if (this.map) {
+            this.setGMapVisibility(false);
+            var cache = OpenLayers.Layer.Google.cache[this.map.id];
+            if (cache && cache.count <= 1) {
+                this.removeGMapElements();
+            }            
+        }
+        OpenLayers.Layer.EventPane.prototype.destroy.apply(this, arguments);
     },
+    
+    /**
+     * Method: removeGMapElements
+     * Remove all elements added to the dom.  This should only be called if
+     * this is the last of the Google layers for the given map.
+     */
+    removeGMapElements: function() {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // remove shared elements from dom
+            var container = this.mapObject && this.getMapContainer();                
+            if (container && container.parentNode) {
+                container.parentNode.removeChild(container);
+            }
+            var termsOfUse = cache.termsOfUse;
+            if (termsOfUse && termsOfUse.parentNode) {
+                termsOfUse.parentNode.removeChild(termsOfUse);
+            }
+            var poweredBy = cache.poweredBy;
+            if (poweredBy && poweredBy.parentNode) {
+                poweredBy.parentNode.removeChild(poweredBy);
+            }
+        }
+    },
 
     /**
      * APIMethod: removeMap
@@ -254,44 +279,29 @@
      * map - {<OpenLayers.Map>}
      */
     removeMap: function(map) {
-        if (this.termsOfUse && this.termsOfUse.parentNode) {
-            this.termsOfUse.parentNode.removeChild(this.termsOfUse);
-            this.termsOfUse = null;
+        // hide layer before removing
+        if (this.visibility && this.mapObject) {
+            this.setGMapVisibility(false);
         }
-        if (this.poweredBy && this.poweredBy.parentNode) {
-            this.poweredBy.parentNode.removeChild(this.poweredBy);
-            this.poweredBy = null;
+        // check to see if last Google layer in this map
+        var cache = OpenLayers.Layer.Google.cache[map.id];
+        if (cache) {
+            if (cache.count <= 1) {
+                this.removeGMapElements();
+                delete OpenLayers.Layer.Google.cache[map.id];
+            } else {
+                // decrement the layer count
+                --cache.count;
+            }
         }
+        // remove references to gmap elements
+        delete this.termsOfUse;
+        delete this.poweredBy;
+        delete this.mapObject;
+        delete this.dragObject;
         OpenLayers.Layer.EventPane.prototype.removeMap.apply(this, arguments);
     },
     
-    /**
-     * APIMethod: getZoomForExtent
-     * 
-     * Parameters:
-     * bounds - {<OpenLayers.Bounds>}
-     *  
-     * Returns:
-     * {Integer} Corresponding zoom level for a specified Bounds. 
-     *           If mapObject is not loaded or not centered, returns null
-     *
-    getZoomForExtent: function (bounds) {
-        var zoom = null;
-        if (this.mapObject != null) {
-            var moBounds = this.getMapObjectBoundsFromOLBounds(bounds);
-            var moZoom = this.getMapObjectZoomFromMapObjectBounds(moBounds);
-
-            //make sure zoom is within bounds    
-            var moZoom = Math.min(Math.max(moZoom, this.minZoomLevel), 
-                                 this.maxZoomLevel);
-
-            zoom = this.getOLZoomFromMapObjectZoom(moZoom);
-        }
-        return zoom;
-    },
-    
-    */
-    
   //
   // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
   //
@@ -327,7 +337,313 @@
         return olBounds;
     },
 
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n("googleWarning");
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
     /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.getCenter();
+    },
+
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.getZoom();
+    },
+
+  
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon :
+          moLonLat.lng();  
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        var lat = this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat :
+          moLonLat.lat(); 
+        return lat;  
+    },
+    
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+    
+    CLASS_NAME: "OpenLayers.Layer.Google"
+});
+
+/**
+ * Property: OpenLayers.Layer.Google.cache
+ * {Object} Cache for elements that should only be created once per map.
+ */
+OpenLayers.Layer.Google.cache = {};
+
+
+/**
+ * Constant: OpenLayers.Layer.Google.v2
+ * 
+ * Mixin providing functionality specific to the Google Maps API v2.
+ */
+OpenLayers.Layer.Google.v2 = {
+    
+    /**
+     * Property: termsOfUse
+     * {DOMElement} Div for Google's copyright and terms of use link
+     */
+    termsOfUse: null, 
+
+    /**
+     * Property: poweredBy
+     * {DOMElement} Div for Google's powered by logo and link
+     */
+    poweredBy: null, 
+
+    /**
+     * Property: dragObject
+     * {GDraggableObject} Since 2.93, Google has exposed the ability to get
+     *     the maps GDraggableObject. We can now use this for smooth panning
+     */
+    dragObject: null, 
+    
+    /** 
+     * Method: loadMapObject
+     * Load the GMap and register appropriate event listeners. If we can't 
+     *     load GMap2, then display a warning message.
+     */
+    loadMapObject:function() {
+        if (!this.type) {
+            this.type = G_NORMAL_MAP;
+        }
+        var mapObject, termsOfUse, poweredBy;
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            // there are already Google layers added to this map
+            mapObject = cache.mapObject;
+            termsOfUse = cache.termsOfUse;
+            poweredBy = cache.poweredBy;
+            // increment the layer count
+            ++cache.count;
+        } else {
+            // this is the first Google layer for this map
+
+            var container = this.map.viewPortDiv;
+            var div = document.createElement("div");
+            div.id = this.map.id + "_GMap2Container";
+            div.style.position = "absolute";
+            div.style.width = "100%";
+            div.style.height = "100%";
+            container.appendChild(div);
+
+            // create GMap and shuffle elements
+            try {
+                mapObject = new GMap2(div);
+                
+                // move the ToS and branding stuff up to the container div
+                termsOfUse = div.lastChild;
+                container.appendChild(termsOfUse);
+                termsOfUse.style.zIndex = "1100";
+                termsOfUse.style.right = "";
+                termsOfUse.style.bottom = "";
+                termsOfUse.className = "olLayerGoogleCopyright";
+
+                poweredBy = div.lastChild;
+                container.appendChild(poweredBy);
+                poweredBy.style.zIndex = "1100";
+                poweredBy.style.right = "";
+                poweredBy.style.bottom = "";
+                poweredBy.className = "olLayerGooglePoweredBy gmnoprint";
+                
+            } catch (e) {
+                throw(e);
+            }
+            // cache elements for use by any other google layers added to
+            // this same map
+            OpenLayers.Layer.Google.cache[this.map.id] = {
+                mapObject: mapObject,
+                termsOfUse: termsOfUse,
+                poweredBy: poweredBy,
+                count: 1
+            };
+        }
+
+        this.mapObject = mapObject;
+        this.termsOfUse = termsOfUse;
+        this.poweredBy = poweredBy;
+        
+        // ensure this layer type is one of the mapObject types
+        if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
+                                    this.type) === -1) {
+            this.mapObject.addMapType(this.type);
+        }
+
+        //since v 2.93 getDragObject is now available.
+        if(typeof mapObject.getDragObject == "function") {
+            this.dragObject = mapObject.getDragObject();
+        } else {
+            this.dragPanMapObject = null;
+        }
+        
+        if(this.isBaseLayer === false) {
+            this.setGMapVisibility(this.div.style.display !== "none");
+        }
+
+    },
+
+    /**
+     * APIMethod: onMapResize
+     */
+    onMapResize: function() {
+        // workaround for resizing of invisible or not yet fully loaded layers
+        // where GMap2.checkResize() does not work. We need to load the GMap
+        // for the old div size, then checkResize(), and then call
+        // layer.moveTo() to trigger GMap.setCenter() (which will finish
+        // the GMap initialization).
+        if(this.visibility && this.mapObject.isLoaded()) {
+            this.mapObject.checkResize();
+        } else {
+            if(!this._resized) {
+                var layer = this;
+                var handle = GEvent.addListener(this.mapObject, "load", function() {
+                    GEvent.removeListener(handle);
+                    delete layer._resized;
+                    layer.mapObject.checkResize();
+                    layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
+                });
+            }
+            this._resized = true;
+        }
+    },
+
+    /**
+     * Method: setGMapVisibility
+     * Display the GMap container and associated elements.
+     * 
+     * Parameters:
+     * visible - {Boolean} Display the GMap elements.
+     */
+    setGMapVisibility: function(visible) {
+        var cache = OpenLayers.Layer.Google.cache[this.map.id];
+        if (cache) {
+            var container = this.mapObject.getContainer();
+            if (visible === true) {
+                this.mapObject.setMapType(this.type);
+                container.style.display = "";
+                this.termsOfUse.style.left = "";
+                this.termsOfUse.style.display = "";
+                this.poweredBy.style.display = "";            
+                cache.displayed = this.id;
+            } else {
+                if (cache.displayed === this.id) {
+                    delete cache.displayed;
+                }
+                if (!cache.displayed) {
+                    container.style.display = "none";
+                    this.termsOfUse.style.display = "none";
+                    // move ToU far to the left in addition to setting display
+                    // to "none", because at the end of the GMap2 load
+                    // sequence, display: none will be unset and ToU would be
+                    // visible after loading a map with a google layer that is
+                    // initially hidden. 
+                    this.termsOfUse.style.left = "-9999px";
+                    this.poweredBy.style.display = "none";
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: getMapContainer
+     * 
+     * Returns:
+     * {DOMElement} the GMap container's div
+     */
+    getMapContainer: function() {
+        return this.mapObject.getContainer();
+    },
+
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
      * APIMethod: getMapObjectBoundsFromOLBounds
      * 
      * Parameters:
@@ -352,49 +668,7 @@
         return moBounds;
     },
 
-    /** 
-     * Method: addContainerPxFunction
-     * Hack-on function because GMAPS does not give it to us
-     * 
-     * Parameters: 
-     * gLatLng - {GLatLng}
-     * 
-     * Returns:
-     * {GPoint} A GPoint specifying gLatLng translated into "Container" coords
-     */
-    addContainerPxFunction: function() {
-        if ( (typeof GMap2 != "undefined") && 
-             !GMap2.prototype.fromLatLngToContainerPixel) {
-          
-            GMap2.prototype.fromLatLngToContainerPixel = function(gLatLng) {
-          
-                // first we translate into "DivPixel"
-                var gPoint = this.fromLatLngToDivPixel(gLatLng);
-      
-                // locate the sliding "Div" div
-                var div = this.getContainer().firstChild.firstChild;
-  
-                // adjust by the offset of "Div" and voila!
-                gPoint.x += div.offsetLeft;
-                gPoint.y += div.offsetTop;
-    
-                return gPoint;
-            };
-        }
-    },
 
-    /** 
-     * APIMethod: getWarningHTML
-     * 
-     * Returns: 
-     * {String} String with information on why layer is broken, how to get
-     *          it working.
-     */
-    getWarningHTML:function() {
-        return OpenLayers.i18n("googleWarning");
-    },
-
-
     /************************************
      *                                  *
      *   MapObject Interface Controls   *
@@ -427,27 +701,7 @@
         this.dragObject.moveBy(new GSize(-dX, dY));
     },
 
-    /**
-     * APIMethod: getMapObjectCenter
-     * 
-     * Returns: 
-     * {Object} The mapObject's current center in Map Object format
-     */
-    getMapObjectCenter: function() {
-        return this.mapObject.getCenter();
-    },
 
-    /** 
-     * APIMethod: getMapObjectZoom
-     * 
-     * Returns:
-     * {Integer} The mapObject's current zoom, in Map Object format
-     */
-    getMapObjectZoom: function() {
-        return this.mapObject.getZoom();
-    },
-
-
   // LonLat - Pixel Translation
   
     /**
@@ -502,37 +756,6 @@
   // LonLat
     
     /**
-     * APIMethod: getLongitudeFromMapObjectLonLat
-     * 
-     * Parameters:
-     * moLonLat - {Object} MapObject LonLat format
-     * 
-     * Returns:
-     * {Float} Longitude of the given MapObject LonLat
-     */
-    getLongitudeFromMapObjectLonLat: function(moLonLat) {
-        return this.sphericalMercator ? 
-          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon :
-          moLonLat.lng();  
-    },
-
-    /**
-     * APIMethod: getLatitudeFromMapObjectLonLat
-     * 
-     * Parameters:
-     * moLonLat - {Object} MapObject LonLat format
-     * 
-     * Returns:
-     * {Float} Latitude of the given MapObject LonLat
-     */
-    getLatitudeFromMapObjectLonLat: function(moLonLat) {
-        var lat = this.sphericalMercator ? 
-          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat :
-          moLonLat.lat(); 
-        return lat;  
-    },
-    
-    /**
      * APIMethod: getMapObjectLonLatFromLonLat
      * 
      * Parameters:
@@ -556,32 +779,6 @@
   // Pixel
     
     /**
-     * APIMethod: getXFromMapObjectPixel
-     * 
-     * Parameters:
-     * moPixel - {Object} MapObject Pixel format
-     * 
-     * Returns:
-     * {Integer} X value of the MapObject Pixel
-     */
-    getXFromMapObjectPixel: function(moPixel) {
-        return moPixel.x;
-    },
-
-    /**
-     * APIMethod: getYFromMapObjectPixel
-     * 
-     * Parameters:
-     * moPixel - {Object} MapObject Pixel format
-     * 
-     * Returns:
-     * {Integer} Y value of the MapObject Pixel
-     */
-    getYFromMapObjectPixel: function(moPixel) {
-        return moPixel.y;
-    },
-
-    /**
      * APIMethod: getMapObjectPixelFromXY
      * 
      * Parameters:
@@ -593,7 +790,6 @@
      */
     getMapObjectPixelFromXY: function(x, y) {
         return new GPoint(x, y);
-    },
-
-    CLASS_NAME: "OpenLayers.Layer.Google"
-});
+    }
+    
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Grid.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Grid.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Grid.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -24,6 +25,12 @@
      */
     tileSize: null,
     
+    /** APIProperty: tileOptions
+     *  {Object} optional configuration options for <OpenLayers.Tile> instances
+     *  created by this Layer, if supported by the tile class.
+     */
+    tileOptions: null,
+    
     /**
      * Property: grid
      * {Array(Array(<OpenLayers.Tile>))} This is an array of rows, each row is 
@@ -130,7 +137,7 @@
             obj = new OpenLayers.Layer.Grid(this.name,
                                             this.url,
                                             this.params,
-                                            this.options);
+                                            this.getOptions());
         }
 
         //get all additions from superclasses
@@ -207,7 +214,7 @@
      */
     setTileSize: function(size) { 
         if (this.singleTile) {
-            size = this.map.getSize().clone();
+            size = this.map.getSize();
             size.h = parseInt(size.h * this.ratio);
             size.w = parseInt(size.w * this.ratio);
         } 
@@ -354,7 +361,7 @@
         var minCols = Math.ceil(viewSize.w/this.tileSize.w) +
                       Math.max(1, 2 * this.buffer);
         
-        var extent = this.maxExtent;
+        var extent = this.getMaxExtent();
         var resolution = this.map.getResolution();
         
         var tileLayout = this.calculateGridLayout(bounds, extent, resolution);
@@ -429,6 +436,18 @@
         //now actually draw the tiles
         this.spiralTileLoad();
     },
+
+    /**
+     * Method: getMaxExtent
+     * Get this layer's maximum extent. (Implemented as a getter for
+     *     potential specific implementations in sub-classes.)
+     *
+     * Returns:
+     * {OpenLayers.Bounds}
+     */
+    getMaxExtent: function() {
+        return this.maxExtent;
+    },
     
     /**
      * Method: spiralTileLoad

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/HTTPRequest.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/HTTPRequest.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/HTTPRequest.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -89,7 +90,7 @@
             obj = new OpenLayers.Layer.HTTPRequest(this.name,
                                                    this.url,
                                                    this.params,
-                                                   this.options);
+                                                   this.getOptions());
         }
         
         //get all additions from superclasses
@@ -121,7 +122,14 @@
      */
     mergeNewParams:function(newParams) {
         this.params = OpenLayers.Util.extend(this.params, newParams);
-        return this.redraw();
+        var ret = this.redraw();
+        if(this.map != null) {
+            this.map.events.triggerEvent("changelayer", {
+                layer: this,
+                property: "params"
+            });
+        }
+        return ret;
     },
 
     /**
@@ -215,25 +223,7 @@
         }
         paramsString = OpenLayers.Util.getParameterString(allParams);
         
-        // requestString always starts with url
-        var requestString = url;        
-        
-        if (paramsString != "") {
-            var lastServerChar = url.charAt(url.length - 1);
-            if ((lastServerChar == "&") || (lastServerChar == "?")) {
-                requestString += paramsString;
-            } else {
-                if (url.indexOf('?') == -1) {
-                    //serverPath has no ? -- add one
-                    requestString += '?' + paramsString;
-                } else {
-                    //serverPath contains ?, so must already have 
-                    // paramsString at the end
-                    requestString += '&' + paramsString;
-                }
-            }
-        }
-        return requestString;
+        return OpenLayers.Util.urlAppend(url, paramsString);
     },
 
     CLASS_NAME: "OpenLayers.Layer.HTTPRequest"

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Image.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Image.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Image.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
  
 /**
@@ -108,7 +109,7 @@
                                                this.url,
                                                this.extent,
                                                this.size,
-                                               this.options);
+                                               this.getOptions());
         }
 
         //get all additions from superclasses

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMap.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMap.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMap.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -162,7 +163,7 @@
             obj = new OpenLayers.Layer.KaMap(this.name,
                                             this.url,
                                             this.params,
-                                            this.options);
+                                            this.getOptions());
         }
 
         //get all additions from superclasses

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMapCache.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMapCache.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/KaMapCache.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapGuide.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapGuide.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapGuide.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * licence.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -224,7 +225,7 @@
             obj = new OpenLayers.Layer.MapGuide(this.name,
                                            this.url,
                                            this.params,
-                                           this.options);
+                                           this.getOptions());
       }
       //get all additions from superclasses
       obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
@@ -264,7 +265,7 @@
     getURL: function (bounds) {
         var url;
         var center = bounds.getCenterLonLat();
-        var mapSize = this.map.getCurrentSize();
+        var mapSize = this.map.getSize();
 
         if (this.singleTile) {
           //set up the call for GETMAPIMAGE or GETDYNAMICMAPOVERLAY with
@@ -353,7 +354,7 @@
         allParams = OpenLayers.Util.extend(allParams, newParams);
         // ignore parameters that are already in the url search string
         var urlParams = OpenLayers.Util.upperCaseObject(
-                            OpenLayers.Util.getArgs(url));
+                            OpenLayers.Util.getParameters(url));
         for(var key in allParams) {
             if(key.toUpperCase() in urlParams) {
                 delete allParams[key];

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer/Untiled.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer/Untiled.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer/Untiled.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright 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. */
+/* 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. */
 
  
 /**
@@ -56,14 +57,14 @@
             obj = new OpenLayers.Layer.MapServer.Untiled(this.name,
                                                          this.url,
                                                          this.params,
-                                                         this.options);
+                                                         this.getOptions());
         }
 
         //get all additions from superclasses
         obj = OpenLayers.Layer.MapServer.prototype.clone.apply(this, [obj]);
 
         // copy/set any non-init, non-simple values here
-
+        
         return obj;
     }, 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/MapServer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -66,7 +67,7 @@
             obj = new OpenLayers.Layer.MapServer(this.name,
                                            this.url,
                                            this.params,
-                                           this.options);
+                                           this.getOptions());
         }
         //get all additions from superclasses
         obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Markers.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Markers.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Markers.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/MultiMap.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/MultiMap.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/MultiMap.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/PointTrack.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/PointTrack.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/PointTrack.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/SphericalMercator.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/SphericalMercator.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/SphericalMercator.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Layer.js
  * @requires OpenLayers/Projection.js
@@ -50,6 +55,38 @@
         return extent;
     },
 
+    /**
+     * Method: getLonLatFromViewPortPx
+     * Get a map location from a pixel location
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     *  {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view
+     *  port OpenLayers.Pixel, translated into lon/lat by map lib
+     *  If the map lib is not loaded or not centered, returns null
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this, arguments);
+    },
+    
+    /**
+     * Method: getViewPortPxFromLonLat
+     * Get a pixel location from a map location
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
+     * OpenLayers.LonLat, translated into view port pixels by map lib
+     * If map lib is not loaded or not centered, returns null
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this, arguments);
+    },
+
     /** 
      * Method: initMercatorParameters 
      * Set up the mercator parameters on the layer: resolutions,
@@ -63,7 +100,7 @@
             this.RESOLUTIONS[zoom] = maxResolution / Math.pow(2, zoom);
         }
         this.units = "m";
-        this.projection = "EPSG:900913";
+        this.projection = this.projection || "EPSG:900913";
     },
 
     /**
@@ -149,11 +186,32 @@
 };
 
 /**
- * Note: Two transforms declared
- * Transforms from EPSG:4326 to EPSG:900913 and from EPSG:900913 to EPSG:4326
- *     are set by this class.
+ * Note: Transforms for web mercator <-> EPSG:4326
+ * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
+ * OpenLayers originally started referring to EPSG:900913 as web mercator.
+ * The EPSG has declared EPSG:3857 to be web mercator.  
+ * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as 
+ * equivalent.  See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084
  */
-OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:900913",
-    OpenLayers.Layer.SphericalMercator.projectForward);
-OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:4326",
-    OpenLayers.Layer.SphericalMercator.projectInverse);
+(function() {
+    
+    // list of equivalent codes for web mercator
+    var codes = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"];
+    
+    var add = OpenLayers.Projection.addTransform;
+    var merc = OpenLayers.Layer.SphericalMercator;
+    var same = OpenLayers.Projection.nullTransform;
+    
+    var i, len, code, other, j;
+    for (i=0, len=codes.length; i<len; ++i) {
+        code = codes[i];
+        add("EPSG:4326", code, merc.projectForward);
+        add(code, "EPSG:4326", merc.projectInverse);
+        for (j=i+1; j<len; ++j) {
+            other = codes[j];
+            add(code, other, same);
+            add(other, code, same);
+        }
+    }
+    
+})();

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/TMS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/TMS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/TMS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * licence.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -42,6 +43,20 @@
     serverResolutions: null,
 
     /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more zoom levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
+     *     setting <serverResolutions> if you only want to expose a subset
+     *     of the server resolutions.
+     */
+    zoomOffset: 0,
+    
+    /**
      * Constructor: OpenLayers.Layer.TMS
      * 
      * Parameters:
@@ -78,7 +93,7 @@
         if (obj == null) {
             obj = new OpenLayers.Layer.TMS(this.name,
                                            this.url,
-                                           this.options);
+                                           this.getOptions());
         }
 
         //get all additions from superclasses
@@ -107,7 +122,7 @@
         var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
         var z = this.serverResolutions != null ?
             OpenLayers.Util.indexOf(this.serverResolutions, res) :
-            this.map.getZoom();
+            this.map.getZoom() + this.zoomOffset;
         var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
         var url = this.url;
         if (url instanceof Array) {

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Text.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Text.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Text.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,10 +1,12 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Layer/Markers.js
+ * @requires OpenLayers/Format/Text.js
  * @requires OpenLayers/Request/XMLHttpRequest.js
  */
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/TileCache.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/TileCache.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/TileCache.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,10 +1,12 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * licence.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
  */
 
 /**
@@ -78,7 +80,7 @@
             obj = new OpenLayers.Layer.TileCache(this.name,
                                                  this.url,
                                                  this.layername,
-                                                 this.options);
+                                                 this.getOptions());
         }
 
         //get all additions from superclasses

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector/RootContainer.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector/RootContainer.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector/RootContainer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Vector.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -54,6 +55,9 @@
      * beforefeatureremoved - Triggered before a feature is removed. Listeners
      *      will receive an object with a *feature* property referencing the
      *      feature to be removed.
+     * beforefeaturesremoved - Triggered before multiple features are removed. 
+     *      Listeners will receive an object with a *features* property
+     *      referencing the features to be removed.
      * featureremoved - Triggerd after a feature is removed. The event
      *      object passed to listeners will have a *feature* property with a
      *      reference to the removed feature.
@@ -97,8 +101,8 @@
      *      for a new set of features.
      */
     EVENT_TYPES: ["beforefeatureadded", "beforefeaturesadded",
-                  "featureadded", "featuresadded",
-                  "beforefeatureremoved", "featureremoved", "featuresremoved",
+                  "featureadded", "featuresadded", "beforefeatureremoved",
+                  "beforefeaturesremoved", "featureremoved", "featuresremoved",
                   "beforefeatureselected", "featureselected", "featureunselected", 
                   "beforefeaturemodified", "featuremodified", "afterfeaturemodified",
                   "vertexmodified", "sketchstarted", "sketchmodified",
@@ -106,8 +110,8 @@
 
     /**
      * APIProperty: isBaseLayer
-     * {Boolean} The layer is a base layer.  Default is true.  Set this property
-     * in the layer options
+     * {Boolean} The layer is a base layer.  Default is false.  Set this property
+     * in the layer options.
      */
     isBaseLayer: false,
 
@@ -119,18 +123,20 @@
     isFixed: false,
 
     /** 
-     * APIProperty: isVector
-     * {Boolean} Whether the layer is a vector layer.
-     */
-    isVector: true,
-    
-    /** 
      * APIProperty: features
      * {Array(<OpenLayers.Feature.Vector>)} 
      */
     features: null,
     
     /** 
+     * Property: filter
+     * {<OpenLayers.Filter>} The filter set in this layer,
+     *     a strategy launching read requests can combined
+     *     this filter with its own filter.
+     */
+    filter: null,
+    
+    /** 
      * Property: selectedFeatures
      * {Array(<OpenLayers.Feature.Vector>)} 
      */
@@ -295,6 +301,36 @@
     },
 
     /**
+     * Method: clone
+     * Create a clone of this layer.
+     * 
+     * Note: Features of the layer are also cloned.
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Vector>} An exact clone of this layer
+     */
+    clone: function (obj) {
+        
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Vector(this.name, this.getOptions());
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+        var features = this.features;
+        var len = features.length;
+        var clonedFeatures = new Array(len);
+        for(var i=0; i<len; ++i) {
+            clonedFeatures[i] = features[i].clone();
+        }
+        obj.features = clonedFeatures;
+
+        return obj;
+    },    
+    
+    /**
      * Method: refresh
      * Ask the layer to request features again and redraw them.  Triggers
      *     the refresh event if the layer is in range and visible.
@@ -316,10 +352,12 @@
      */    
     assignRenderer: function()  {
         for (var i=0, len=this.renderers.length; i<len; i++) {
-            var rendererClass = OpenLayers.Renderer[this.renderers[i]];
-            if (rendererClass && rendererClass.prototype.supported()) {
-                this.renderer = new rendererClass(this.div,
-                    this.rendererOptions);
+            var rendererClass = this.renderers[i];
+            var renderer = (typeof rendererClass == "function") ?
+                rendererClass :
+                OpenLayers.Renderer[rendererClass];
+            if (renderer && renderer.prototype.supported()) {
+                this.renderer = new renderer(this.div, this.rendererOptions);
                 break;
             }  
         }  
@@ -383,6 +421,7 @@
      * map - {<OpenLayers.Map>}
      */
     removeMap: function(map) {
+        this.drawn = false;
         if(this.strategies) {
             var strategy, i, len;
             for(i=0, len=this.strategies.length; i<len; i++) {
@@ -437,7 +476,7 @@
             // Force a reflow on gecko based browsers to prevent jump/flicker.
             // This seems to happen on only certain configurations; it was originally
             // noticed in FF 2.0 and Linux.
-            if (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) {
+            if (OpenLayers.IS_GECKO === true) {
                 this.div.scrollLeft = this.div.scrollLeft;
             }
             
@@ -500,7 +539,9 @@
             features = event.features;
         }
         
-
+        // Track successfully added features for featuresadded event, since
+        // beforefeatureadded can veto single features.
+        var featuresAdded = [];
         for (var i=0, len=features.length; i<len; i++) {
             if (i != (features.length - 1)) {
                 this.renderer.locked = true;
@@ -516,8 +557,6 @@
                 throw throwStr;
               }
 
-            this.features.push(feature);
-            
             //give feature reference to its layer
             feature.layer = this;
 
@@ -533,6 +572,8 @@
                 this.preFeatureInsert(feature);
             }
 
+            featuresAdded.push(feature);
+            this.features.push(feature);
             this.drawFeature(feature);
             
             if (notify) {
@@ -544,7 +585,7 @@
         }
         
         if(notify) {
-            this.events.triggerEvent("featuresadded", {features: features});
+            this.events.triggerEvent("featuresadded", {features: featuresAdded});
         }
     },
 
@@ -570,14 +611,23 @@
         if(!features || features.length === 0) {
             return;
         }
+        if (features === this.features) {
+            return this.removeAllFeatures(options);
+        }
         if (!(features instanceof Array)) {
             features = [features];
         }
-        if (features === this.features) {
+        if (features === this.selectedFeatures) {
             features = features.slice();
         }
 
         var notify = !options || !options.silent;
+        
+        if (notify) {
+            this.events.triggerEvent(
+                "beforefeaturesremoved", {features: features}
+            );
+        }
 
         for (var i = features.length - 1; i >= 0; i--) {
             // We remain locked so long as we're not at 0
@@ -628,6 +678,49 @@
             this.events.triggerEvent("featuresremoved", {features: features});
         }
     },
+    
+    /** 
+     * APIMethod: removeAllFeatures
+     * Remove all features from the layer.
+     *
+     * Parameters:
+     * options - {Object} Optional properties for changing behavior of the
+     *     removal.
+     *
+     * Valid options:
+     * silent - {Boolean} Supress event triggering.  Default is false.
+     */
+    removeAllFeatures: function(options) {
+        var notify = !options || !options.silent;
+        var features = this.features;
+        if (notify) {
+            this.events.triggerEvent(
+                "beforefeaturesremoved", {features: features}
+            );
+        }
+        var feature;
+        for (var i = features.length-1; i >= 0; i--) {
+            feature = features[i];
+            if (notify) {
+                this.events.triggerEvent("beforefeatureremoved", {
+                    feature: feature
+                });
+            }
+            feature.layer = null;
+            if (notify) {
+                this.events.triggerEvent("featureremoved", {
+                    feature: feature
+                });
+            }
+        }
+        this.renderer.clear();
+        this.features = [];
+        this.unrenderedFeatures = {};
+        this.selectedFeatures = [];
+        if (notify) {
+            this.events.triggerEvent("featuresremoved", {features: features});
+        }
+    },
 
     /**
      * APIMethod: destroyFeatures
@@ -669,7 +762,7 @@
      *
      * Parameters: 
      * feature - {<OpenLayers.Feature.Vector>} 
-     * style - {Object} Symbolizer hash or {String} renderIntent
+     * style - {String | Object} Named render intent or full symbolizer object.
      */
     drawFeature: function(feature, style) {
         // don't try to draw the feature with the renderer if the layer is not 
@@ -725,31 +818,62 @@
         var featureId = this.renderer.getFeatureIdFromEvent(evt);
         return this.getFeatureById(featureId);
     },
-    
+
     /**
-     * APIMethod: getFeatureById
-     * Given a feature id, return the feature if it exists in the features array
+     * APIMethod: getFeatureBy
+     * Given a property value, return the feature if it exists in the features array
      *
      * Parameters:
-     * featureId - {String} 
+     * property - {String}
+     * value - {String}
      *
      * Returns:
      * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
-     * featureId
+     * property value or null if there is no such feature.
      */
-    getFeatureById: function(featureId) {
+    getFeatureBy: function(property, value) {
         //TBD - would it be more efficient to use a hash for this.features?
         var feature = null;
         for(var i=0, len=this.features.length; i<len; ++i) {
-            if(this.features[i].id == featureId) {
+            if(this.features[i][property] == value) {
                 feature = this.features[i];
                 break;
             }
         }
         return feature;
     },
-    
+
     /**
+     * APIMethod: getFeatureById
+     * Given a feature id, return the feature if it exists in the features array
+     *
+     * Parameters:
+     * featureId - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+     * featureId or null if there is no such feature.
+     */
+    getFeatureById: function(featureId) {
+        return this.getFeatureBy('id', featureId);
+    },
+
+    /**
+     * APIMethod: getFeatureByFid
+     * Given a feature fid, return the feature if it exists in the features array
+     *
+     * Parameters:
+     * featureFid - {String}
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+     * featureFid or null if there is no such feature.
+     */
+    getFeatureByFid: function(featureFid) {
+        return this.getFeatureBy('fid', featureFid);
+    },
+
+    /**
      * Unselect the selected features
      * i.e. clears the featureSelection array
      * change the style back
@@ -799,14 +923,17 @@
      */
     getDataExtent: function () {
         var maxExtent = null;
-
-        if(this.features && (this.features.length > 0)) {
+        var features = this.features;
+        if(features && (features.length > 0)) {
             maxExtent = new OpenLayers.Bounds();
-            for(var i=0, len=this.features.length; i<len; i++) {
-                maxExtent.extend(this.features[i].geometry.getBounds());
+            var geometry = null;
+            for(var i=0, len=features.length; i<len; i++) {
+                geometry = features[i].geometry;
+                if (geometry) {
+                    maxExtent.extend(geometry.getBounds());
+                }
             }
         }
-
         return maxExtent;
     },
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/VirtualEarth.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/VirtualEarth.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/VirtualEarth.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,9 +1,11 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Layer/SphericalMercator.js
  * @requires OpenLayers/Layer/EventPane.js
  * @requires OpenLayers/Layer/FixedZoomLevels.js
  */
@@ -27,9 +29,9 @@
     
     /** 
      * Constant: MAX_ZOOM_LEVEL
-     * {Integer} 17
+     * {Integer} 19
      */
-    MAX_ZOOM_LEVEL: 17,
+    MAX_ZOOM_LEVEL: 19,
 
     /** 
      * Constant: RESOLUTIONS
@@ -53,7 +55,9 @@
         0.000171661376953125, 
         0.0000858306884765625, 
         0.00004291534423828125,
-        0.00002145767211914062
+        0.00002145767211914062, 
+        0.00001072883605957031,
+        0.00000536441802978515
     ],
 
     /**
@@ -63,13 +67,29 @@
     type: null,
 
     /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
      * APIProperty: sphericalMercator
      * {Boolean} Should the map act as a mercator-projected map? This will
      *     cause all interactions with the map to be in the actual map
      *     projection, which allows support for vector drawing, overlaying
      *     other maps, etc. 
      */
-    sphericalMercator: false, 
+    sphericalMercator: false,
+    
+    /**
+     * APIProperty: animationEnabled
+     * {Boolean} If set to true, the transition between zoom levels will be
+     *     animated. Set to false to match the zooming experience of other
+     *     layer types. Default is true.
+     */
+    animationEnabled: true, 
 
     /** 
      * Constructor: OpenLayers.Layer.VirtualEarth
@@ -112,10 +132,13 @@
                 // http://blogs.msdn.com/virtualearth/archive/2007/09/28/locking-a-virtual-earth-map.aspx
                 //
                 this.mapObject.LoadMap(null, null, this.type, true);
-                this.mapObject.AttachEvent("onmousedown", function() {return true; });
+                this.mapObject.AttachEvent("onmousedown", OpenLayers.Function.True);
 
             } catch (e) { }
             this.mapObject.HideDashboard();
+            if(typeof this.mapObject.SetAnimationEnabled == "function") {
+                this.mapObject.SetAnimationEnabled(this.animationEnabled);
+            }
         }
 
         //can we do smooth panning? this is an unpublished method, so we need 
@@ -130,6 +153,13 @@
 
     },
 
+    /**
+     * Method: onMapResize
+     */
+    onMapResize: function() {
+        this.mapObject.Resize(this.map.size.w, this.map.size.h);
+    },
+
     /** 
      * APIMethod: getWarningHTML
      * 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WFS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WFS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WFS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -12,6 +13,8 @@
 
 /**
  * Class: OpenLayers.Layer.WFS
+ * *Deprecated*.  To be removed in 3.0.  Instead use OpenLayers.Layer.Vector
+ *     with a Protocol.WFS and one or more Strategies.
  * 
  * Inherits from:
  *  - <OpenLayers.Layer.Vector>
@@ -34,8 +37,13 @@
     
     /**
      * APIProperty: ratio
-     * {Float} the ratio of image/tile size to map size (this is the untiled
-     *     buffer)
+     * {Float} The ratio property determines the size of the serverside query
+     *    relative to the map viewport size. By default, we load an area twice
+     *    as big as the map, to allow for panning without immediately reload.
+     *    Setting this to 1 will cause the area of the WFS request to match
+     *    the map area exactly. It is recommended to set this to some number
+     *    at least slightly larger than 1, otherwise accidental clicks can
+     *    cause a data reload, by moving the map only 1 pixel.
      */
     ratio: 2,
 
@@ -119,6 +127,9 @@
             !OpenLayers.Feature.Vector) {
             this.vectorMode = false;
         }    
+
+        // Uppercase params
+        params = OpenLayers.Util.upperCaseObject(params);
         
         // Turn off error reporting, browsers like Safari may work
         // depending on the setup, and we don't want an unneccesary alert.
@@ -435,7 +446,7 @@
             obj = new OpenLayers.Layer.WFS(this.name,
                                            this.url,
                                            this.params,
-                                           this.options);
+                                           this.getOptions());
         }
 
         //get all additions from superclasses

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Post.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Layer/WMS/Post.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Post.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Post.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,103 @@
+/* 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/Layer/WMS.js
+ * @requires OpenLayers/Tile/Image/IFrame.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMS.Post
+ * Instances of OpenLayers.Layer.WMS.Post are used to retrieve data from OGC
+ * Web Mapping Services via HTTP-POST (application/x-www-form-urlencoded). 
+ * Create a new WMS layer with the <OpenLayers.Layer.WMS.Post> constructor.
+ *
+ * *Deprecated*. Instead of this layer, use <OpenLayers.Layer.WMS> with
+ * <OpenLayers.Tile.Image.maxGetUrlLength> configured in the layer's
+ * <OpenLayers.Layer.WMS.tileOptions>.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.WMS>
+ */
+OpenLayers.Layer.WMS.Post = OpenLayers.Class(OpenLayers.Layer.WMS, {
+
+    /**
+     * APIProperty: unsupportedBrowsers
+     * {Array} Array with browsers, which should use the HTTP-GET protocol 
+     * instead of HTTP-POST for fetching tiles from a WMS .
+     * Defaults to ["mozilla", "firefox", "opera"], because Opera is not able 
+     * to show transparent images in IFrames and Firefox/Mozilla has some ugly 
+     * effects of viewport-shaking when panning the map. Both browsers, Opera
+     * and Firefox/Mozilla, have no problem with long urls, which is the reason
+     * for using POST instead of GET. The strings to pass to this array are
+     * the ones returned by <OpenLayers.BROWSER_NAME>.
+     */
+    unsupportedBrowsers: ["mozilla", "firefox", "opera"],
+
+    /**
+     * Property: SUPPORTED_TRANSITIONS
+     * {Array} 
+     * no supported transitions for this type of layer, because it is not
+     * possible to modify the initialized tiles (iframes)
+     */
+    SUPPORTED_TRANSITIONS: [],
+    
+    /**
+     * Property: usePost
+     * {Boolean}
+     */
+    usePost: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.WMS.Post
+     * Creates a new WMS layer object.
+     *
+     * Example:
+     * (code)
+     * var wms = new OpenLayers.Layer.WMS.Post(
+     *  "NASA Global Mosaic",
+     *  "http://wms.jpl.nasa.gov/wms.cgi",
+     *  {layers: "modis, global_mosaic"});
+     * (end)
+     *
+     * Parameters:
+     * name - {String} A name for the layer
+     * url - {String} Base url for the WMS
+     *                (e.g. http://wms.jpl.nasa.gov/wms.cgi)
+     * params - {Object} An object with key/value pairs representing the
+     *                   GetMap query string parameters and parameter values.
+     * options - {Object} Hashtable of extra options to tag onto the layer.
+     */
+    initialize: function(name, url, params, options) {
+        var newArguments = [];
+        newArguments.push(name, url, params, options);
+        OpenLayers.Layer.WMS.prototype.initialize.apply(this, newArguments);
+
+        this.usePost = OpenLayers.Util.indexOf(
+            this.unsupportedBrowsers, OpenLayers.BROWSER_NAME) == -1;
+    },
+    
+    /**
+     * Method: addTile
+     * addTile creates a tile, initializes it and adds it as iframe to the
+     * layer div.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.Tile.Image.IFrame>} The added OpenLayers.Tile.Image.IFrame
+     */
+    addTile: function(bounds,position) {
+        return new OpenLayers.Tile.Image(
+            this, position, bounds, null, this.tileSize, {
+                maxGetUrlLength: this.usePost ? 0 : null
+            });
+    },
+
+    CLASS_NAME: 'OpenLayers.Layer.WMS.Post'
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Untiled.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Untiled.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS/Untiled.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
  
@@ -56,7 +57,7 @@
             obj = new OpenLayers.Layer.WMS.Untiled(this.name,
                                                    this.url,
                                                    this.params,
-                                                   this.options);
+                                                   this.getOptions());
         }
 
         //get all additions from superclasses

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -62,9 +63,17 @@
      *     TRANSPARENT=TRUE. Also isBaseLayer will not changed by the  
      *     constructor. Default false. 
      */ 
-    noMagic: false,  
+    noMagic: false,
     
     /**
+     * Property: yx
+     * {Object} Keys in this object are EPSG codes for which the axis order
+     *     is to be reversed (yx instead of xy, LatLon instead of LonLat), with
+     *     true as value. This is only relevant for WMS versions >= 1.3.0.
+     */
+    yx: {'EPSG:4326': true},
+    
+    /**
      * Constructor: OpenLayers.Layer.WMS
      * Create a new WMS layer object
      *
@@ -87,6 +96,9 @@
         var newArguments = [];
         //uppercase params
         params = OpenLayers.Util.upperCaseObject(params);
+        if (parseFloat(params.VERSION) >= 1.3 && !params.EXCEPTIONS) {
+            params.EXCEPTIONS = "INIMAGE";
+        } 
         newArguments.push(name, url, params, options);
         OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
         OpenLayers.Util.applyDefaults(
@@ -137,7 +149,7 @@
             obj = new OpenLayers.Layer.WMS(this.name,
                                            this.url,
                                            this.params,
-                                           this.options);
+                                           this.getOptions());
         }
 
         //get all additions from superclasses
@@ -149,6 +161,19 @@
     },    
     
     /**
+     * APIMethod: reverseAxisOrder
+     * Returns true if the axis order is reversed for the WMS version and
+     * projection of the layer.
+     * 
+     * Returns:
+     * {Boolean} true if the axis order is reversed, false otherwise.
+     */
+    reverseAxisOrder: function() {
+        return (parseFloat(this.params.VERSION) >= 1.3 && 
+            !!this.yx[this.map.getProjectionObject().getCode()]);
+    },
+    
+    /**
      * Method: getURL
      * Return a GetMap query string for this layer
      *
@@ -164,12 +189,15 @@
     getURL: function (bounds) {
         bounds = this.adjustBounds(bounds);
         
-        var imageSize = this.getImageSize(); 
-        var newParams = {
-            'BBOX': this.encodeBBOX ?  bounds.toBBOX() : bounds.toArray(),
-            'WIDTH': imageSize.w,
-            'HEIGHT': imageSize.h
-        };
+        var imageSize = this.getImageSize();
+        var newParams = {};
+        // WMS 1.3 introduced axis order
+        var reverseAxisOrder = this.reverseAxisOrder();
+        newParams.BBOX = this.encodeBBOX ?
+            bounds.toBBOX(null, reverseAxisOrder) :
+            bounds.toArray(reverseAxisOrder);
+        newParams.WIDTH = imageSize.w;
+        newParams.HEIGHT = imageSize.h;
         var requestString = this.getFullRequestString(newParams);
         return requestString;
     },
@@ -187,7 +215,7 @@
      */
     addTile:function(bounds,position) {
         return new OpenLayers.Tile.Image(this, position, bounds, 
-                                         null, this.tileSize);
+                                         null, this.tileSize, this.tileOptions);
     },
 
     /**
@@ -224,8 +252,16 @@
      * {String} 
      */
     getFullRequestString:function(newParams, altUrl) {
-        var projectionCode = this.map.getProjection();
-        this.params.SRS = (projectionCode == "none") ? null : projectionCode;
+        var mapProjection = this.map.getProjectionObject();
+        var projectionCode = this.projection.equals(mapProjection) ?
+            this.projection.getCode() :
+            mapProjection.getCode();
+        var value = (projectionCode == "none") ? null : projectionCode
+        if (parseFloat(this.params.VERSION) >= 1.3) {
+            this.params.CRS = value;
+        } else {
+            this.params.SRS = value;
+        }
 
         return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
                                                     this, arguments);

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMTS.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Layer/WMTS.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMTS.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WMTS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,476 @@
+/* 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/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.WMTS
+ * Instances of the WMTS class allow viewing of tiles from a service that 
+ *     implements the OGC WMTS specification version 1.0.0.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
+    
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean} The layer will be considered a base layer.  Default is true.
+     */
+    isBaseLayer: true,
+
+    /**
+     * Property: version
+     * {String} WMTS version.  Default is "1.0.0".
+     */
+    version: "1.0.0",
+    
+    /**
+     * APIProperty: requestEncoding
+     * {String} Request encoding.  Can be "REST" or "KVP".  Default is "KVP".
+     */
+    requestEncoding: "KVP",
+    
+    /**
+     * APIProperty: url
+     * {String} The base URL for the WMTS service.  Must be provided.
+     */
+    url: null,
+
+    /**
+     * APIProperty: layer
+     * {String} The layer identifier advertised by the WMTS service.  Must be 
+     *     provided.
+     */
+    layer: null,
+    
+    /** 
+     * APIProperty: matrixSet
+     * {String} One of the advertised matrix set identifiers.  Must be provided.
+     */
+    matrixSet: null,
+
+    /** 
+     * APIProperty: style
+     * {String} One of the advertised layer styles.  Must be provided.
+     */
+    style: null,
+    
+    /** 
+     * APIProperty: format
+     * {String} The image MIME type.  Default is "image/jpeg".
+     */
+    format: "image/jpeg",
+    
+    /**
+     * APIProperty: tileOrigin
+     * {<OpenLayers.LonLat>} The top-left corner of the tile matrix in map 
+     *     units.  If the tile origin for each matrix in a set is different,
+     *     the <matrixIds> should include a topLeftCorner property.  If
+     *     not provided, the tile origin will default to the top left corner
+     *     of the layer <maxExtent>.
+     */
+    tileOrigin: null,
+    
+    /**
+     * APIProperty: tileFullExtent
+     * {<OpenLayers.Bounds>}  The full extent of the tile set.  If not supplied,
+     *     the layer's <maxExtent> property will be used.
+     */
+    tileFullExtent: null,
+
+    /**
+     * APIProperty: formatSuffix
+     * {String} For REST request encoding, an image format suffix must be 
+     *     included in the request.  If not provided, the suffix will be derived
+     *     from the <format> property.
+     */
+    formatSuffix: null,    
+
+    /**
+     * APIProperty: matrixIds
+     * {Array} A list of tile matrix identifiers.  If not provided, the matrix
+     *     identifiers will be assumed to be integers corresponding to the 
+     *     map zoom level.  If a list of strings is provided, each item should
+     *     be the matrix identifier that corresponds to the map zoom level.
+     *     Additionally, a list of objects can be provided.  Each object should
+     *     describe the matrix as presented in the WMTS capabilities.  These
+     *     objects should have the propertes shown below.
+     * 
+     * Matrix properties:
+     * identifier - {String} The matrix identifier (required).
+     * topLeftCorner - {<OpenLayers.LonLat>} The top left corner of the 
+     *     matrix.  Must be provided if different than the layer <tileOrigin>.
+     * tileWidth - {Number} The tile width for the matrix.  Must be provided 
+     *     if different than the width given in the layer <tileSize>.
+     * tileHeight - {Number} The tile height for the matrix.  Must be provided 
+     *     if different than the height given in the layer <tileSize>.
+     */
+    matrixIds: null,
+    
+    /**
+     * APIProperty: dimensions
+     * {Array} For RESTful request encoding, extra dimensions may be specified.
+     *     Items in this list should be property names in the <params> object.
+     *     Values of extra dimensions will be determined from the corresponding
+     *     values in the <params> object.
+     */
+    dimensions: null,
+    
+    /**
+     * APIProperty: params
+     * {Object} Extra parameters to include in tile requests.  For KVP 
+     *     <requestEncoding>, these properties will be encoded in the request 
+     *     query string.  For REST <requestEncoding>, these properties will
+     *     become part of the request path, with order determined by the 
+     *     <dimensions> list.
+     */
+    params: null,
+    
+    /**
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Additionally, if this layer is to be used
+     *     as an overlay and the cache has fewer zoom levels than the base
+     *     layer, you can supply a negative zoomOffset.  For example, if a
+     *     map zoom level of 1 corresponds to your cache level zero, you would
+     *     supply a -1 zoomOffset (and set the maxResolution of the layer
+     *     appropriately).  The zoomOffset value has no effect if complete
+     *     matrix definitions (including scaleDenominator) are supplied in
+     *     the <matrixIds> property.  Defaults to 0 (no zoom offset).
+     */
+    zoomOffset: 0,
+    
+    /**
+     * Property: formatSuffixMap
+     * {Object} a map between WMTS 'format' request parameter and tile image file suffix
+     */
+    formatSuffixMap: {
+        "image/png": "png",
+        "image/png8": "png",
+        "image/png24": "png",
+        "image/png32": "png",
+        "png": "png",
+        "image/jpeg": "jpg",
+        "image/jpg": "jpg",
+        "jpeg": "jpg",
+        "jpg": "jpg"
+    },
+    
+    /**
+     * Property: matrix
+     * {Object} Matrix definition for the current map resolution.  Updated by
+     *     the <updateMatrixProperties> method.
+     */
+    matrix: null,
+    
+    /**
+     * Constructor: OpenLayers.Layer.WMTS
+     * Create a new WMTS layer.
+     *
+     * Example:
+     * (code)
+     * var wmts = new OpenLayers.Layer.WMTS({
+     *     name: "My WMTS Layer",
+     *     url: "http://example.com/wmts", 
+     *     layer: "layer_id",
+     *     style: "default",
+     *     matrixSet: "matrix_id"
+     * });
+     * (end)
+     *
+     * Parameters:
+     * config - {Object} Configuration properties for the layer.
+     *
+     * Required configuration properties:
+     * url - {String} The base url for the service.  See the <url> property.
+     * layer - {String} The layer identifier.  See the <layer> property.
+     * style - {String} The layer style identifier.  See the <style> property.
+     * matrixSet - {String} The tile matrix set identifier.  See the <matrixSet>
+     *     property.
+     *
+     * Any other documented layer properties can be provided in the config object.
+     */
+    initialize: function(config) {
+
+        // confirm required properties are supplied
+        var required = {
+            url: true,
+            layer: true,
+            style: true,
+            matrixSet: true
+        };
+        for (var prop in required) {
+            if (!(prop in config)) {
+                throw new Error("Missing property '" + prop + "' in layer configuration.");
+            }
+        }
+
+        config.params = OpenLayers.Util.upperCaseObject(config.params);
+        var args = [config.name, config.url, config.params, config];
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, args);
+        
+
+        // determine format suffix (for REST)
+        if (!this.formatSuffix) {
+            this.formatSuffix = this.formatSuffixMap[this.format] || this.format.split("/").pop();            
+        }
+
+        // expand matrixIds (may be array of string or array of object)
+        if (this.matrixIds) {
+            var len = this.matrixIds.length;
+            if (len && typeof this.matrixIds[0] === "string") {
+                var ids = this.matrixIds;
+                this.matrixIds = new Array(len);
+                for (var i=0; i<len; ++i) {
+                    this.matrixIds[i] = {identifier: ids[i]};
+                }
+            }
+        }
+
+    },
+    
+    /**
+     * Method: setMap
+     */
+    setMap: function() {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        this.updateMatrixProperties();
+    },
+    
+    /**
+     * Method: updateMatrixProperties
+     * Called when map resolution changes to update matrix related properties.
+     */
+    updateMatrixProperties: function() {
+        this.matrix = this.getMatrix();
+        if (this.matrix) {
+            if (this.matrix.topLeftCorner) {
+                this.tileOrigin = this.matrix.topLeftCorner;
+            }
+            if (this.matrix.tileWidth && this.matrix.tileHeight) {
+                this.tileSize = new OpenLayers.Size(
+                    this.matrix.tileWidth, this.matrix.tileHeight
+                );
+            }
+            if (!this.tileOrigin) { 
+                this.tileOrigin = new OpenLayers.LonLat(
+                    this.maxExtent.left, this.maxExtent.top
+                );
+            }   
+            if (!this.tileFullExtent) { 
+                this.tileFullExtent = this.maxExtent;
+            }
+        }
+    },
+    
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * bound - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to
+     *     do some init work in that case.
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        if (zoomChanged || !this.matrix) {
+            this.updateMatrixProperties();
+        }
+        return OpenLayers.Layer.Grid.prototype.moveTo.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: clone
+     * 
+     * Parameters:
+     * obj - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Layer.WMTS>} An exact clone of this <OpenLayers.Layer.WMTS>
+     */
+    clone: function(obj) {
+        if (obj == null) {
+            obj = new OpenLayers.Layer.WMTS(this.options);
+        }
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+        // copy/set any non-init, non-simple values here
+        return obj;
+    },
+    
+    /**
+     * Method: getMatrix
+     * Get the appropriate matrix definition for the current map resolution.
+     */
+    getMatrix: function() {
+        var matrix;
+        if (!this.matrixIds || this.matrixIds.length === 0) {
+            matrix = {identifier: this.map.getZoom() + this.zoomOffset};
+        } else {
+            // get appropriate matrix given the map scale if possible
+            if ("scaleDenominator" in this.matrixIds[0]) {
+                // scale denominator calculation based on WMTS spec
+                var denom = 
+                    OpenLayers.METERS_PER_INCH * 
+                    OpenLayers.INCHES_PER_UNIT[this.units] * 
+                    this.map.getResolution() / 0.28E-3;
+                var diff = Number.POSITIVE_INFINITY;
+                var delta;
+                for (var i=0, ii=this.matrixIds.length; i<ii; ++i) {
+                    delta = Math.abs(1 - (this.matrixIds[i].scaleDenominator / denom));
+                    if (delta < diff) {
+                        diff = delta;
+                        matrix = this.matrixIds[i];
+                    }
+                }
+            } else {
+                // fall back on zoom as index
+                matrix = this.matrixIds[this.map.getZoom() + this.zoomOffset];
+            }
+        }
+        return matrix;
+    },
+    
+    /** 
+     * Method: getTileInfo
+     * Get tile information for a given location at the current map resolution.
+     *
+     * Parameters:
+     * loc - {<OpenLayers.LonLat} A location in map coordinates.
+     *
+     * Returns:
+     * {Object} An object with "col", "row", "i", and "j" properties.  The col
+     *     and row values are zero based tile indexes from the top left.  The
+     *     i and j values are the number of pixels to the left and top 
+     *     (respectively) of the given location within the target tile.
+     */
+    getTileInfo: function(loc) {
+        var res = this.map.getResolution();
+        
+        var fx = (loc.lon - this.tileOrigin.lon) / (res * this.tileSize.w);
+        var fy = (this.tileOrigin.lat - loc.lat) / (res * this.tileSize.h);
+
+        var col = Math.floor(fx);
+        var row = Math.floor(fy);
+        
+        return {
+            col: col, 
+            row: row,
+            i: Math.floor((fx - col) * this.tileSize.w),
+            j: Math.floor((fy - row) * this.tileSize.h)
+        };
+    },
+    
+    /**
+     * Method: getURL
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {String} A URL for the tile corresponding to the given bounds.
+     */
+    getURL: function(bounds) {
+        bounds = this.adjustBounds(bounds);
+        var url = "";
+        if (!this.tileFullExtent || this.tileFullExtent.intersectsBounds(bounds)) {            
+
+            var center = bounds.getCenterLonLat();            
+            var info = this.getTileInfo(center);
+            var matrixId = this.matrix.identifier;
+
+            if (this.requestEncoding.toUpperCase() === "REST") {
+
+                // include 'version', 'layer' and 'style' in tile resource url
+                var path = this.version + "/" + this.layer + "/" + this.style + "/";
+
+                // append optional dimension path elements
+                if (this.dimensions) {
+                    for (var i=0; i<this.dimensions.length; i++) {
+                        if (this.params[this.dimensions[i]]) {
+                            path = path + this.params[this.dimensions[i]] + "/";
+                        }
+                    }
+                }
+
+                // append other required path elements
+                path = path + this.matrixSet + "/" + this.matrix.identifier + 
+                    "/" + info.row + "/" + info.col + "." + this.formatSuffix;
+                
+                if (this.url instanceof Array) {
+                    url = this.selectUrl(path, this.url);
+                } else {
+                    url = this.url;
+                }
+                if (!url.match(/\/$/)) {
+                    url = url + "/";
+                }
+                url = url + path;
+
+            } else if (this.requestEncoding.toUpperCase() === "KVP") {
+
+                // assemble all required parameters
+                var params = {
+                    SERVICE: "WMTS",
+                    REQUEST: "GetTile",
+                    VERSION: this.version,
+                    LAYER: this.layer,
+                    STYLE: this.style,
+                    TILEMATRIXSET: this.matrixSet,
+                    TILEMATRIX: this.matrix.identifier,
+                    TILEROW: info.row,
+                    TILECOL: info.col,
+                    FORMAT: this.format
+                };
+                url = OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this, [params]);
+
+            }
+        }
+        return url;    
+    },
+    
+    /**
+     * APIMethod: mergeNewParams
+     * Extend the existing layer <params> with new properties.  Tiles will be
+     *     reloaded with updated params in the request.
+     * 
+     * Parameters:
+     * newParams - {Object} Properties to extend to existing <params>.
+     */
+    mergeNewParams: function(newParams) {
+        if (this.requestEncoding.toUpperCase() === "KVP") {
+            return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(
+                this, [OpenLayers.Util.upperCaseObject(newParams)]
+            );
+        }
+    },
+
+    /**
+     * Method: addTile
+     * Create a tile, initialize it, and add it to the layer div. 
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {<OpenLayers.Tile.Image>} The added OpenLayers.Tile.Image
+     */
+    addTile: function(bounds,position) {
+        return new OpenLayers.Tile.Image(this, position, bounds, 
+                                         null, this.tileSize);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.WMTS"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/WorldWind.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/WorldWind.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/WorldWind.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/XYZ.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/XYZ.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/XYZ.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,15 +1,20 @@
-/* Copyright (c) 2006-2009 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
  */
 
 /** 
  * Class: OpenLayers.Layer.XYZ
  * The XYZ class is designed to make it easier for people who have tiles
  * arranged by a standard XYZ grid. 
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
  */
 OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, {
     
@@ -28,7 +33,28 @@
     sphericalMercator: false,
 
     /**
-     * Constructor: OpenLayers.Layer.OSM
+     * APIProperty: zoomOffset
+     * {Number} If your cache has more zoom levels than you want to provide
+     *     access to with this layer, supply a zoomOffset.  This zoom offset
+     *     is added to the current map zoom level to determine the level
+     *     for a requested tile.  For example, if you supply a zoomOffset
+     *     of 3, when the map is at the zoom 0, tiles will be requested from
+     *     level 3 of your cache.  Default is 0 (assumes cache level and map
+     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
+     *     setting <serverResolutions> if you only want to expose a subset
+     *     of the server resolutions.
+     */
+    zoomOffset: 0,
+    
+    /**
+     * APIProperty: serverResolutions
+     * {Array} A list of all resolutions available on the server.  Only set this
+     *     property if the map resolutions differs from the server.
+     */
+    serverResolutions: null,
+
+    /**
+     * Constructor: OpenLayers.Layer.XYZ
      *
      * Parameters:
      * name - {String}
@@ -64,27 +90,19 @@
      * obj - {Object} Is this ever used?
      * 
      * Returns:
-     * {<OpenLayers.Layer.Grid>} An exact clone of this OpenLayers.Layer.Grid
+     * {<OpenLayers.Layer.XYZ>} An exact clone of this OpenLayers.Layer.XYZ
      */
     clone: function (obj) {
         
         if (obj == null) {
             obj = new OpenLayers.Layer.XYZ(this.name,
                                             this.url,
-                                            this.options);
+                                            this.getOptions());
         }
 
         //get all additions from superclasses
-        obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]);
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
 
-        // copy/set any non-init, non-simple values here
-        if (this.tileSize != null) {
-            obj.tileSize = this.tileSize.clone();
-        }
-        
-        // we do not want to copy reference to grid, so we make a new array
-        obj.grid = [];
-
         return obj;
     },    
 
@@ -105,8 +123,9 @@
             / (res * this.tileSize.w));
         var y = Math.round((this.maxExtent.top - bounds.top) 
             / (res * this.tileSize.h));
-        var z = this.map.getZoom();
-        var limit = Math.pow(2, z);
+        var z = this.serverResolutions != null ?
+            OpenLayers.Util.indexOf(this.serverResolutions, res) :
+            this.map.getZoom() + this.zoomOffset;
 
         var url = this.url;
         var s = '' + x + y + z;
@@ -167,12 +186,22 @@
  * (end)
  *
  * This layer defaults to Spherical Mercator.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.XYZ>
  */
-
 OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, {
      name: "OpenStreetMap",
      attribution: "Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",
      sphericalMercator: true,
      url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png',
+     clone: function(obj) {
+         if (obj == null) {
+             obj = new OpenLayers.Layer.OSM(
+                 this.name, this.url, this.getOptions());
+         }
+         obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+         return obj;
+     },
      CLASS_NAME: "OpenLayers.Layer.OSM"
 });

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Yahoo.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Yahoo.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Yahoo.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,9 +1,11 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Layer/SphericalMercator.js
  * @requires OpenLayers/Layer/EventPane.js
  * @requires OpenLayers/Layer/FixedZoomLevels.js
  */
@@ -63,6 +65,14 @@
     type: null,
     
     /**
+     * APIProperty: wrapDateLine
+     * {Boolean} Allow user to pan forever east/west.  Default is true.  
+     *     Setting this to false only restricts panning if 
+     *     <sphericalMercator> is true. 
+     */
+    wrapDateLine: true,
+
+    /**
      * APIProperty: sphericalMercator
      * {Boolean} Should the map act as a mercator-projected map? This will
      * cause all interactions with the map to be in the actual map projection,

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Layer/Zoomify.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Layer/Zoomify.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer/Zoomify.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer/Zoomify.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,308 @@
+/* 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. */
+
+/*
+ * Development supported by a R&D grant DC08P02OUK006 - Old Maps Online
+ * (www.oldmapsonline.org) from Ministry of Culture of the Czech Republic.
+ */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Zoomify
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.Zoomify = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Property: url
+     * {String} URL for root directory with TileGroupX subdirectories.
+     */
+    url: null,
+
+    /**
+     * Property: size
+     * {<OpenLayers.Size>} The Zoomify image size in pixels.
+     */
+    size: null,
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean}
+     */
+    isBaseLayer: true,
+
+    /**
+     * Property: standardTileSize
+     * {Integer} The size of a standard (non-border) square tile in pixels.
+     */
+    standardTileSize: 256,
+
+    /**
+     * Property: numberOfTiers
+     * {Integer} Depth of the Zoomify pyramid, number of tiers (zoom levels)
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    numberOfTiers: 0,
+
+    /**
+     * Property: tileCountUpToTier
+     * {Array(Integer)} Number of tiles up to the given tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tileCountUpToTier: new Array(),
+
+    /**
+     * Property: tierSizeInTiles
+     * {Array(<OpenLayers.Size>)} Size (in tiles) for each tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierSizeInTiles: new Array(),
+
+    /**
+     * Property: tierImageSize
+     * {Array(<OpenLayers.Size>)} Image size in pixels for each pyramid tier.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierImageSize: new Array(),
+
+    /**
+     * Constructor: OpenLayers.Layer.Zoomify
+     *
+     * Parameters:
+     * name - {String} A name for the layer.
+     * url - {String} - Relative or absolute path to the image or more
+     *        precisly to the TileGroup[X] directories root.
+     *        Flash plugin use the variable name "zoomifyImagePath" for this.
+     * size - {<OpenLayers.Size>} The size (in pixels) of the image.
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, size, options) {
+
+        // initilize the Zoomify pyramid for given size
+        this.initializeZoomify( size );
+
+        var newArguments = [];
+        newArguments.push(name, url, size, {}, options);
+
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },
+
+    /**
+     * Method: initializeZoomify
+     * It generates constants for all tiers of the Zoomify pyramid
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} The size of the image in pixels
+     *
+     */
+    initializeZoomify: function( size ) {
+
+        var imageSize = size.clone()
+        var tiles = new OpenLayers.Size(
+            Math.ceil( imageSize.w / this.standardTileSize ),
+            Math.ceil( imageSize.h / this.standardTileSize )
+            );
+
+        this.tierSizeInTiles.push( tiles );
+        this.tierImageSize.push( imageSize );
+
+        while (imageSize.w > this.standardTileSize ||
+               imageSize.h > this.standardTileSize ) {
+
+            imageSize = new OpenLayers.Size(
+                Math.floor( imageSize.w / 2 ),
+                Math.floor( imageSize.h / 2 )
+                );
+            tiles = new OpenLayers.Size(
+                Math.ceil( imageSize.w / this.standardTileSize ),
+                Math.ceil( imageSize.h / this.standardTileSize )
+                );
+            this.tierSizeInTiles.push( tiles );
+            this.tierImageSize.push( imageSize );
+        }
+
+        this.tierSizeInTiles.reverse();
+        this.tierImageSize.reverse();
+
+        this.numberOfTiers = this.tierSizeInTiles.length;
+
+        this.tileCountUpToTier[0] = 0;
+        for (var i = 1; i < this.numberOfTiers; i++) {
+            this.tileCountUpToTier.push(
+                this.tierSizeInTiles[i-1].w * this.tierSizeInTiles[i-1].h +
+                this.tileCountUpToTier[i-1]
+                );
+        }
+    },
+
+    /**
+     * APIMethod:destroy
+     */
+    destroy: function() {
+        // for now, nothing special to do here.
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
+
+        // Remove from memory the Zoomify pyramid - is that enough?
+        this.tileCountUpToTier.length = 0
+        this.tierSizeInTiles.length = 0
+        this.tierImageSize.length = 0
+
+    },
+
+    /**
+     * APIMethod: clone
+     *
+     * Parameters:
+     * obj - {Object}
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Zoomify>} An exact clone of this <OpenLayers.Layer.Zoomify>
+     */
+    clone: function (obj) {
+
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Zoomify(this.name,
+                                           this.url,
+                                           this.size,
+                                           this.options);
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+        var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+        var z = this.map.getZoom();
+
+        var tileIndex = x + y * this.tierSizeInTiles[z].w + this.tileCountUpToTier[z];
+        var path = "TileGroup" + Math.floor( (tileIndex) / 256 ) +
+            "/" + z + "-" + x + "-" + y + ".jpg";
+        var url = this.url;
+        if (url instanceof Array) {
+            url = this.selectUrl(path, url);
+        }
+        return url + path;
+    },
+
+    /**
+     * Method: getImageSize
+     * getImageSize returns size for a particular tile. If bounds are given as
+     * first argument, size is calculated (bottom-right tiles are non square).
+     *
+     */
+    getImageSize: function() {
+        if (arguments.length > 0) {
+            bounds = this.adjustBounds(arguments[0]);
+            var res = this.map.getResolution();
+            var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+            var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+            var z = this.map.getZoom();
+            var w = this.standardTileSize;
+            var h = this.standardTileSize;
+            if (x == this.tierSizeInTiles[z].w -1 ) {
+                var w = this.tierImageSize[z].w % this.standardTileSize;
+            };
+            if (y == this.tierSizeInTiles[z].h -1 ) {
+                var h = this.tierImageSize[z].h % this.standardTileSize;
+            };
+            return (new OpenLayers.Size(w, h));
+        } else {
+            return this.tileSize;
+        }
+    },
+
+    /**
+     * Method: addTile
+     * addTile creates a tile, initializes it, and adds it to the layer div.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.Tile.Image>} The added OpenLayers.Tile.Image
+     */
+    addTile:function(bounds,position) {
+        return new OpenLayers.Tile.Image(this, position, bounds,
+                                         null, this.tileSize);
+    },
+
+    /**
+     * APIMethod: setMap
+     * When the layer is added to a map, then we can fetch our origin
+     *    (if we don't have one.)
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
+                                                this.map.maxExtent.top);
+    },
+
+    /**
+     * Method: calculateGridLayout
+     * Generate parameters for the grid layout. This
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * extent - {<OpenLayers.Bounds>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, extent, resolution) {
+        var tilelon = resolution * this.tileSize.w;
+        var tilelat = resolution * this.tileSize.h;
+
+        var offsetlon = bounds.left - extent.left;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = extent.left + tilecol * tilelon;
+
+        var offsetlat = extent.top - bounds.top + tilelat;
+        var tilerow = Math.floor(offsetlat/tilelat) - this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = tilerowremain * this.tileSize.h;
+        var tileoffsetlat = extent.top - tilelat*tilerow;
+
+        return {
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Zoomify"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Layer.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Layer.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Layer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -82,8 +83,20 @@
      */
     EVENT_TYPES: ["loadstart", "loadend", "loadcancel", "visibilitychanged",
                   "move", "moveend"],
-        
+
     /**
+     * Constant: RESOLUTION_PROPERTIES
+     * {Array} The properties that are used for calculating resolutions
+     *     information.
+     */
+    RESOLUTION_PROPERTIES: [
+        'scales', 'resolutions',
+        'maxScale', 'minScale',
+        'maxResolution', 'minResolution',
+        'numZoomLevels', 'maxZoomLevel'
+    ],
+
+    /**
      * APIProperty: events
      * {<OpenLayers.Events>}
      */
@@ -300,6 +313,13 @@
      *     transitionEffect values.
      */
     SUPPORTED_TRANSITIONS: ['resize'],
+
+    /**
+     * Property: metadata
+     * {Object} This object can be used to store additional information on a
+     *     layer object.
+     */
+    metadata: {},
     
     /**
      * Constructor: OpenLayers.Layer
@@ -380,8 +400,8 @@
     clone: function (obj) {
         
         if (obj == null) {
-            obj = new OpenLayers.Layer(this.name, this.options);
-        } 
+            obj = new OpenLayers.Layer(this.name, this.getOptions());
+        }
         
         // catch any randomly tagged-on properties
         OpenLayers.Util.applyDefaults(obj, this);
@@ -393,6 +413,23 @@
         return obj;
     },
     
+    /**
+     * Method: getOptions
+     * Extracts an object from the layer with the properties that were set as
+     *     options, but updates them with the values currently set on the
+     *     instance.
+     * 
+     * Returns:
+     * {Object} the <options> of the layer, representing the current state.
+     */
+    getOptions: function() {
+        var options = {};
+        for(var o in this.options) {
+            options[o] = this[o];
+        }
+        return options;
+    },
+    
     /** 
      * APIMethod: setName
      * Sets the new layer name for this layer.  Can trigger a changelayer event
@@ -420,18 +457,46 @@
     * newOptions - {Object}
     */
     addOptions: function (newOptions) {
-        
+
         if (this.options == null) {
             this.options = {};
         }
-        
+
         // update our copy for clone
         OpenLayers.Util.extend(this.options, newOptions);
 
         // add new options to this
         OpenLayers.Util.extend(this, newOptions);
+
+        // make sure this.projection references a projection object
+        if(typeof this.projection == "string") {
+            this.projection = new OpenLayers.Projection(this.projection);
+        }
+
+        // get the units from the projection, if we have a projection
+        // and it it has units
+        if(this.projection && this.projection.getUnits()) {
+            this.units = this.projection.getUnits();
+        }
+
+        // re-initialize resolutions if necessary, i.e. if any of the
+        // properties of the "properties" array defined below is set
+        // in the new options
+        if(this.map) {
+            var properties = this.RESOLUTION_PROPERTIES.concat(
+                ["projection", "units", "minExtent", "maxExtent"]
+            );
+            for(var o in newOptions) {
+                if(newOptions.hasOwnProperty(o) &&
+                   OpenLayers.Util.indexOf(properties, o) >= 0) {
+
+                    this.initResolutions();
+                    break;
+                }
+            }
+        }
     },
-    
+
     /**
      * APIMethod: onMapResize
      * This function can be implemented by subclasses
@@ -505,12 +570,13 @@
             // grab some essential layer data from the map if it hasn't already
             //  been set
             this.maxExtent = this.maxExtent || this.map.maxExtent;
+            this.minExtent = this.minExtent || this.map.minExtent;
+
             this.projection = this.projection || this.map.projection;
-            
-            if (this.projection && typeof this.projection == "string") {
+            if (typeof this.projection == "string") {
                 this.projection = new OpenLayers.Projection(this.projection);
             }
-            
+
             // Check the projection to see if we can get units -- if not, refer
             // to properties.
             this.units = this.projection.getUnits() ||
@@ -555,12 +621,17 @@
     
     /**
      * APIMethod: getImageSize
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>} optional tile bounds, can be used
+     *     by subclasses that have to deal with different tile sizes at the
+     *     layer extent edges (e.g. Zoomify)
      * 
      * Returns:
      * {<OpenLayers.Size>} The size that the image should be, taking into 
      *     account gutters.
      */ 
-    getImageSize: function() { 
+    getImageSize: function(bounds) { 
         return (this.imageSize || this.tileSize); 
     },    
   
@@ -633,15 +704,16 @@
 
     /** 
      * APIMethod: display
-     * Hide or show the Layer
+     * Hide or show the Layer. This is designed to be used internally, and 
+     *     is not generally the way to enable or disable the layer. For that,
+     *     use the setVisibility function instead..
      * 
      * Parameters:
      * display - {Boolean}
      */
     display: function(display) {
-        var inRange = this.calculateInRange();
         if (display != (this.div.style.display != "none")) {
-            this.div.style.display = (display && inRange) ? "block" : "none";
+            this.div.style.display = (display && this.calculateInRange()) ? "block" : "none";
         }
     },
 
@@ -706,184 +778,242 @@
      */
     initResolutions: function() {
 
-        // These are the relevant options which are used for calculating 
-        //  resolutions information.
+        // ok we want resolutions, here's our strategy:
         //
-        var props = new Array(
-          'projection', 'units',
-          'scales', 'resolutions',
-          'maxScale', 'minScale', 
-          'maxResolution', 'minResolution', 
-          'minExtent', 'maxExtent',
-          'numZoomLevels', 'maxZoomLevel'
-        );
+        // 1. if resolutions are defined in the layer config, use them
+        // 2. else, if scales are defined in the layer config then derive
+        //    resolutions from these scales
+        // 3. else, attempt to calculate resolutions from maxResolution,
+        //    minResolution, numZoomLevels, maxZoomLevel set in the
+        //    layer config
+        // 4. if we still don't have resolutions, and if resolutions
+        //    are defined in the same, use them
+        // 5. else, if scales are defined in the map then derive
+        //    resolutions from these scales
+        // 6. else, attempt to calculate resolutions from maxResolution,
+        //    minResolution, numZoomLevels, maxZoomLevel set in the
+        //    map
+        // 7. hope for the best!
 
-        //these are the properties which do *not* imply that user wishes 
-        // this layer to be scale-dependant
-        var notScaleProps = ['projection', 'units'];    
+        var i, len;
+        var props = {}, alwaysInRange = true;
 
-        //should the layer be scale-dependant? default is false -- this will 
-        // only be set true if we find that the user has specified a property
-        // from the 'props' array that is not in 'notScaleProps'
-        var useInRange = false;
-
-        // First we create a new object where we will store all of the 
-        //  resolution-related properties that we find in either the layer's
-        //  'options' array or from the map.
-        //
-        var confProps = {};        
-        for(var i=0, len=props.length; i<len; i++) {
-            var property = props[i];
-            
-            // If the layer had one of these properties set *and* it is 
-            // a scale property (is not a non-scale property), then we assume
-            // the user did intend to use scale-dependant display (useInRange).
-            if (this.options[property] && 
-                OpenLayers.Util.indexOf(notScaleProps, property) == -1) {
-                useInRange = true;
+        // get resolution data from layer config
+        // (we also set alwaysInRange in the layer as appropriate)
+        for(i=0, len=this.RESOLUTION_PROPERTIES.length; i<len; i++) {
+            var p = this.RESOLUTION_PROPERTIES[i];
+            props[p] = this.options[p];
+            if(alwaysInRange && this.options[p]) {
+                alwaysInRange = false;
             }
-                   
-            confProps[property] = this.options[property] || this.map[property];
         }
+        if(this.alwaysInRange == null) {
+            this.alwaysInRange = alwaysInRange;
+        }
 
-        //only automatically set 'alwaysInRange' if the user hasn't already 
-        // set it (to true or false, since the default is null). If user did
-        // not intend to use scale-dependant display then we set they layer
-        // as alwaysInRange. This means calculateInRange() will always return 
-        // true and the layer will never be turned off due to scale changes.
-        //
-        if (this.alwaysInRange == null) {
-            this.alwaysInRange = !useInRange;
+        // if we don't have resolutions then attempt to derive them from scales
+        if(props.resolutions == null) {
+            props.resolutions = this.resolutionsFromScales(props.scales);
         }
 
-        // Do not use the scales array set at the map level if 
-        // either minScale or maxScale or both are set at the
-        // layer level
-        if ((this.options.minScale != null ||
-             this.options.maxScale != null) &&
-            this.options.scales == null) {
+        // if we still don't have resolutions then attempt to calculate them
+        if(props.resolutions == null) {
+            props.resolutions = this.calculateResolutions(props);
+        }
 
-            confProps.scales = null;
+        // if we couldn't calculate resolutions then we look at we have
+        // in the map
+        if(props.resolutions == null) {
+            for(i=0, len=this.RESOLUTION_PROPERTIES.length; i<len; i++) {
+                var p = this.RESOLUTION_PROPERTIES[i];
+                props[p] = this.options[p] != null ?
+                    this.options[p] : this.map[p];
+            }
+            if(props.resolutions == null) {
+                props.resolutions = this.resolutionsFromScales(props.scales);
+            }
+            if(props.resolutions == null) {
+                props.resolutions = this.calculateResolutions(props);
+            }
         }
-        // Do not use the resolutions array set at the map level if 
-        // either minResolution or maxResolution or both are set at the
-        // layer level
-        if ((this.options.minResolution != null ||
-             this.options.maxResolution != null) &&
-            this.options.resolutions == null) {
 
-            confProps.resolutions = null;
+        // ok, we new need to set properties in the instance
+
+        // get maxResolution from the config if it's defined there
+        var maxResolution;
+        if(this.options.maxResolution &&
+           this.options.maxResolution !== "auto") {
+            maxResolution = this.options.maxResolution;
         }
+        if(this.options.minScale) {
+            maxResolution = OpenLayers.Util.getResolutionFromScale(
+                this.options.minScale, this.units);
+        }
 
-        // If numZoomLevels hasn't been set and the maxZoomLevel *has*, 
-        //  then use maxZoomLevel to calculate numZoomLevels
-        //
-        if ( (!confProps.numZoomLevels) && (confProps.maxZoomLevel) ) {
-            confProps.numZoomLevels = confProps.maxZoomLevel + 1;
+        // get minResolution from the config if it's defined there
+        var minResolution;
+        if(this.options.minResolution &&
+           this.options.minResolution !== "auto") {
+            minResolution = this.options.minResolution;
         }
+        if(this.options.maxScale) {
+            minResolution = OpenLayers.Util.getResolutionFromScale(
+                this.options.maxScale, this.units);
+        }
 
-        // First off, we take whatever hodge-podge of values we have and 
-        //  calculate/distill them down into a resolutions[] array
-        //
-        if ((confProps.scales != null) || (confProps.resolutions != null)) {
-          //preset levels
-            if (confProps.scales != null) {
-                confProps.resolutions = [];
-                for(var i=0, len=confProps.scales.length; i<len; i++) {
-                    var scale = confProps.scales[i];
-                    confProps.resolutions[i] = 
-                       OpenLayers.Util.getResolutionFromScale(scale, 
-                                                              confProps.units);
-                }
+        if(props.resolutions) {
+
+            //sort resolutions array descendingly
+            props.resolutions.sort(function(a, b) {
+                return (b - a);
+            });
+
+            // if we still don't have a maxResolution get it from the
+            // resolutions array
+            if(!maxResolution) {
+                maxResolution = props.resolutions[0];
             }
-            confProps.numZoomLevels = confProps.resolutions.length;
 
-        } else {
-          //maxResolution and numZoomLevels based calculation
+            // if we still don't have a minResolution get it from the
+            // resolutions array
+            if(!minResolution) {
+                var lastIdx = props.resolutions.length - 1;
+                minResolution = props.resolutions[lastIdx];
+            }
+        }
 
-            // determine maxResolution
-            if (confProps.minScale) {
-                confProps.maxResolution = 
-                    OpenLayers.Util.getResolutionFromScale(confProps.minScale, 
-                                                           confProps.units);
-            } else if (confProps.maxResolution == "auto") {
-                var viewSize = this.map.getSize();
-                var wRes = confProps.maxExtent.getWidth() / viewSize.w;
-                var hRes = confProps.maxExtent.getHeight()/ viewSize.h;
-                confProps.maxResolution = Math.max(wRes, hRes);
-            } 
+        this.resolutions = props.resolutions;
+        if(this.resolutions) {
+            len = this.resolutions.length;
+            this.scales = new Array(len);
+            for(i=0; i<len; i++) {
+                this.scales[i] = OpenLayers.Util.getScaleFromResolution(
+                    this.resolutions[i], this.units);
+            }
+            this.numZoomLevels = len;
+        }
+        this.minResolution = minResolution;
+        if(minResolution) {
+            this.maxScale = OpenLayers.Util.getScaleFromResolution(
+                minResolution, this.units);
+        }
+        this.maxResolution = maxResolution;
+        if(maxResolution) {
+            this.minScale = OpenLayers.Util.getScaleFromResolution(
+                maxResolution, this.units);
+        }
+    },
 
-            // determine minResolution
-            if (confProps.maxScale != null) {           
-                confProps.minResolution = 
-                    OpenLayers.Util.getResolutionFromScale(confProps.maxScale, 
-                                                           confProps.units);
-            } else if ( (confProps.minResolution == "auto") && 
-                        (confProps.minExtent != null) ) {
-                var viewSize = this.map.getSize();
-                var wRes = confProps.minExtent.getWidth() / viewSize.w;
-                var hRes = confProps.minExtent.getHeight()/ viewSize.h;
-                confProps.minResolution = Math.max(wRes, hRes);
-            } 
+    /**
+     * Method: resolutionsFromScales
+     * Derive resolutions from scales.
+     *
+     * Parameters:
+     * scales - {Array(Number)} Scales
+     *
+     * Returns
+     * {Array(Number)} Resolutions
+     */
+    resolutionsFromScales: function(scales) {
+        if(scales == null) {
+            return;
+        }
+        var resolutions, i, len;
+        len = scales.length;
+        resolutions = new Array(len);
+        for(i=0; i<len; i++) {
+            resolutions[i] = OpenLayers.Util.getResolutionFromScale(
+                scales[i], this.units);
+        }
+        return resolutions;
+    },
 
-            // determine numZoomLevels if not already set on the layer
-            // this gives numZoomLevels assuming approximately base 2 scaling
-            if (confProps.minResolution != null &&
-                this.options.numZoomLevels == undefined) {
-                var ratio = confProps.maxResolution / confProps.minResolution;
-                confProps.numZoomLevels = 
-                    Math.floor(Math.log(ratio) / Math.log(2)) + 1;
+    /**
+     * Method: calculateResolutions
+     * Calculate resolutions based on the provided properties.
+     *
+     * Parameters:
+     * props - {Object} Properties
+     *
+     * Return:
+     * {Array({Number})} Array of resolutions.
+     */
+    calculateResolutions: function(props) {
+
+        // determine maxResolution
+        var maxResolution = props.maxResolution;
+        if(props.minScale != null) {
+            maxResolution =
+                OpenLayers.Util.getResolutionFromScale(props.minScale,
+                                                       this.units);
+        } else if(maxResolution == "auto" && this.maxExtent != null) {
+            var viewSize = this.map.getSize();
+            var wRes = this.maxExtent.getWidth() / viewSize.w;
+            var hRes = this.maxExtent.getHeight() / viewSize.h;
+            maxResolution = Math.max(wRes, hRes);
+        }
+
+        // determine minResolution
+        var minResolution = props.minResolution;
+        if(props.maxScale != null) {
+            minResolution =
+                OpenLayers.Util.getResolutionFromScale(props.maxScale,
+                                                       this.units);
+        } else if(props.minResolution == "auto" && this.minExtent != null) {
+            var viewSize = this.map.getSize();
+            var wRes = this.minExtent.getWidth() / viewSize.w;
+            var hRes = this.minExtent.getHeight()/ viewSize.h;
+            minResolution = Math.max(wRes, hRes);
+        }
+
+        // determine numZoomLevels
+        var maxZoomLevel = props.maxZoomLevel;
+        var numZoomLevels = props.numZoomLevels;
+        if(typeof minResolution === "number" &&
+           typeof maxResolution === "number" && numZoomLevels === undefined) {
+            var ratio = maxResolution / minResolution;
+            numZoomLevels = Math.floor(Math.log(ratio) / Math.log(2)) + 1;
+        } else if(numZoomLevels === undefined && maxZoomLevel != null) {
+            numZoomLevels = maxZoomLevel + 1;
+        }
+
+        // are we able to calculate resolutions?
+        if(typeof numZoomLevels !== "number" || numZoomLevels <= 0 ||
+           (typeof maxResolution !== "number" &&
+                typeof minResolution !== "number")) {
+            return;
+        }
+
+        // now we have numZoomLevels and at least one of maxResolution
+        // or minResolution, we can populate the resolutions array
+
+        var resolutions = new Array(numZoomLevels);
+        var base = 2;
+        if(typeof minResolution == "number" &&
+           typeof maxResolution == "number") {
+            // if maxResolution and minResolution are set, we calculate
+            // the base for exponential scaling that starts at
+            // maxResolution and ends at minResolution in numZoomLevels
+            // steps.
+            base = Math.pow(
+                    (maxResolution / minResolution),
+                (1 / (numZoomLevels - 1))
+            );
+        }
+
+        var i;
+        if(typeof maxResolution === "number") {
+            for(i=0; i<numZoomLevels; i++) {
+                resolutions[i] = maxResolution / Math.pow(base, i);
             }
-            
-            // now we have numZoomLevels and maxResolution, 
-            //  we can populate the resolutions array
-            confProps.resolutions = new Array(confProps.numZoomLevels);
-            var base = 2;
-            if(typeof confProps.minResolution == "number" &&
-               confProps.numZoomLevels > 1) {
-                /**
-                 * If maxResolution and minResolution are set (or related
-                 * scale properties), we calculate the base for exponential
-                 * scaling that starts at maxResolution and ends at
-                 * minResolution in numZoomLevels steps.
-                 */
-                base = Math.pow(
-                    (confProps.maxResolution / confProps.minResolution),
-                    (1 / (confProps.numZoomLevels - 1))
-                );
+        } else {
+            for(i=0; i<numZoomLevels; i++) {
+                resolutions[numZoomLevels - 1 - i] =
+                    minResolution * Math.pow(base, i);
             }
-            for (var i=0; i < confProps.numZoomLevels; i++) {
-                var res = confProps.maxResolution / Math.pow(base, i);
-                confProps.resolutions[i] = res;
-            }
         }
-        
-        //sort resolutions array ascendingly
-        //
-        confProps.resolutions.sort( function(a, b) { return(b-a); } );
 
-        // now set our newly calculated values back to the layer 
-        //  Note: We specifically do *not* set them to layer.options, which we 
-        //        will preserve as it was when we added this layer to the map. 
-        //        this way cloned layers reset themselves to new map div 
-        //        dimensions)
-        //
-
-        this.resolutions = confProps.resolutions;
-        this.maxResolution = confProps.resolutions[0];
-        var lastIndex = confProps.resolutions.length - 1;
-        this.minResolution = confProps.resolutions[lastIndex];
-        
-        this.scales = [];
-        for(var i=0, len=confProps.resolutions.length; i<len; i++) {
-            this.scales[i] = 
-               OpenLayers.Util.getScaleFromResolution(confProps.resolutions[i], 
-                                                      confProps.units);
-        }
-        this.minScale = this.scales[0];
-        this.maxScale = this.scales[this.scales.length - 1];
-        
-        this.numZoomLevels = confProps.numZoomLevels;
+        return resolutions;
     },
 
     /**
@@ -1109,6 +1239,12 @@
                 OpenLayers.Util.modifyDOMElement(element, null, null, null, 
                                                  null, null, null, opacity);
             }
+            if (this.map != null) {
+                this.map.events.triggerEvent("changelayer", {
+                    layer: this,
+                    property: "opacity"
+                });
+            }
         }
     },
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Map.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Map.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Map.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -61,25 +62,20 @@
      *  - *removelayer* triggered after a layer has been removed.  The event
      *      object will include a *layer* property that references the removed
      *      layer.
-     *  - *changelayer* triggered after a layer name change, order change, or
-     *      visibility change (due to resolution thresholds).  Listeners will
-     *      receive an event object with *layer* and *property* properties.  The
-     *      *layer* property will be a reference to the changed layer.  The
-     *      *property* property will be a key to the changed property (name,
-     *      visibility, or order).
+     *  - *changelayer* triggered after a layer name change, order change,
+     *      opacity change, params change or visibility change
+     *      (due to resolution thresholds). Listeners will receive an event
+     *      object with *layer* and *property* properties. The *layer*
+     *      property will be a reference to the changed layer. 
+     *      The *property* property will be a key to the
+     *      changed property (name, order, opacity, params or visibility).
      *  - *movestart* triggered after the start of a drag, pan, or zoom
      *  - *move* triggered after each drag, pan, or zoom
      *  - *moveend* triggered after a drag, pan, or zoom completes
      *  - *zoomend* triggered after a zoom completes
-     *  - *addmarker* triggered after a marker has been added
-     *  - *removemarker* triggered after a marker has been removed
-     *  - *clearmarkers* triggered after markers have been cleared
      *  - *mouseover* triggered after mouseover the map
      *  - *mouseout* triggered after mouseout the map
      *  - *mousemove* triggered after mousemove the map
-     *  - *dragstart* Does not work.  Register for movestart instead.
-     *  - *drag* Does not work.  Register for move instead.
-     *  - *dragend* Does not work.  Register for moveend instead.
      *  - *changebaselayer* triggered after the base layer changes
      */
     EVENT_TYPES: [ 
@@ -148,7 +144,8 @@
      *     is not provided, the map can be rendered to a container later
      *     using the <render> method.
      *     
-     * Note: If you calling <render> after map construction, do not use
+     * Note:
+     * If you are calling <render> after map construction, do not use
      *     <maxResolution>  auto.  Instead, divide your <maxExtent> by your
      *     maximum expected dimension.
      */
@@ -422,9 +419,9 @@
      *     ways to call the map constructor.  See the examples below.
      *
      * Parameters:
-     * div - {String} Id of an element in your page that will contain the map.
-     *     May be omitted if the <div> option is provided or if you intend
-     *     to use <render> later.
+     * div - {DOMElement|String}  The element or id of an element in your page
+     *     that will contain the map.  May be omitted if the <div> option is
+     *     provided or if you intend to call the <render> method later.
      * options - {Object} Optional object with properties to tag onto the map.
      *
      * Examples (method one):
@@ -484,6 +481,9 @@
         // now override default options 
         OpenLayers.Util.extend(this, options);
 
+        // initialize layers array
+        this.layers = [];
+
         this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_");
 
         this.div = OpenLayers.Util.getElement(div);
@@ -496,7 +496,7 @@
         OpenLayers.Element.addClass(this.div, 'olMap');
 
         // the viewPortDiv is the outermost div we modify
-        var id = this.div.id + "_OpenLayers_ViewPort";
+        var id = this.id + "_OpenLayers_ViewPort";
         this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,
                                                      "relative", null,
                                                      "hidden");
@@ -506,14 +506,14 @@
         this.div.appendChild(this.viewPortDiv);
 
         // the layerContainerDiv is the one that holds all the layers
-        id = this.div.id + "_OpenLayers_Container";
+        id = this.id + "_OpenLayers_Container";
         this.layerContainerDiv = OpenLayers.Util.createDiv(id);
         this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
         
         this.viewPortDiv.appendChild(this.layerContainerDiv);
 
         this.events = new OpenLayers.Events(this, 
-                                            this.div, 
+                                            this.viewPortDiv, 
                                             this.EVENT_TYPES, 
                                             this.fallThrough, 
                                             {includeXY: true});
@@ -562,8 +562,6 @@
                 document.getElementsByTagName('head')[0].appendChild(cssNode);
             }
         }
-
-        this.layers = [];
         
         if (this.controls == null) {
             if (OpenLayers.Control != null) { // running full or lite?
@@ -588,6 +586,16 @@
 
         // always call map.destroy()
         OpenLayers.Event.observe(window, 'unload', this.unloadDestroy);
+        
+        // add any initial layers
+        if (options && options.layers) {
+            this.addLayers(options.layers);        
+            // set center (and optionally zoom)
+            if (options.center) {
+                // zoom can be undefined here
+                this.setCenter(options.center, options.zoom);
+            }
+        }
     },
     
     /**
@@ -602,7 +610,6 @@
     render: function(div) {
         this.div = OpenLayers.Util.getElement(div);
         OpenLayers.Element.addClass(this.div, 'olMap');
-        this.events.attachToElement(this.div);
         this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
         this.div.appendChild(this.viewPortDiv);
         this.updateSize();
@@ -632,6 +639,12 @@
         if (!this.unloadDestroy) {
             return false;
         }
+        
+        // make sure panning doesn't continue after destruction
+        if(this.panTween) {
+            this.panTween.stop();
+            this.panTween = null;
+        }
 
         // map has been destroyed. dont do it again!
         OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
@@ -900,7 +913,9 @@
             layer.isBaseLayer = false;
         }
 
-        this.events.triggerEvent("preaddlayer", {layer: layer});
+        if (this.events.triggerEvent("preaddlayer", {layer: layer}) === false) {
+            return;
+        }
         
         layer.div.className = "olLayerDiv";
         layer.div.style.overflow = "";
@@ -1089,16 +1104,18 @@
      * newBaseLayer - {<OpenLayers.Layer>}
      */
     setBaseLayer: function(newBaseLayer) {
-        var oldExtent = null;
-        if (this.baseLayer) {
-            oldExtent = this.baseLayer.getExtent();
-        }
-
+        
         if (newBaseLayer != this.baseLayer) {
           
-            // is newBaseLayer an already loaded layer?m
+            // ensure newBaseLayer is already loaded
             if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
 
+                // preserve center and scale when changing base layers
+                var center = this.getCenter();
+                var newResolution = OpenLayers.Util.getResolutionFromScale(
+                    this.getScale(), newBaseLayer.units
+                );
+
                 // make the old base layer invisible 
                 if (this.baseLayer != null && !this.allOverlays) {
                     this.baseLayer.setVisibility(false);
@@ -1111,28 +1128,18 @@
                 // changing. This is used by tiles to check if they should 
                 // draw themselves.
                 this.viewRequestID++;
-                if(!this.allOverlays) {
-                    this.baseLayer.visibility = true;
+                if(!this.allOverlays || this.baseLayer.visibility) {
+                    this.baseLayer.setVisibility(true);
                 }
 
-                //redraw all layers
-                var center = this.getCenter();
+                // recenter the map
                 if (center != null) {
-
-                    //either get the center from the old Extent or just from
-                    // the current center of the map. 
-                    var newCenter = (oldExtent) 
-                        ? oldExtent.getCenterLonLat()
-                        : center;
-
-                    //the new zoom will either come from the old Extent or 
-                    // from the current resolution of the map                                                
-                    var newZoom = (oldExtent) 
-                        ? this.getZoomForExtent(oldExtent, true)
-                        : this.getZoomForResolution(this.resolution, true);
-
+                    // new zoom level derived from old scale
+                    var newZoom = this.getZoomForResolution(
+                        newResolution || this.resolution, true
+                    );
                     // zoom and force zoom change
-                    this.setCenter(newCenter, newZoom, false, true);
+                    this.setCenter(center, newZoom, false, true);
                 }
 
                 this.events.triggerEvent("changebaselayer", {
@@ -1154,6 +1161,8 @@
 
     /**
      * APIMethod: addControl
+     * Add the passed over control to the map. Optionally 
+     *     position the control at the given pixel.
      * 
      * Parameters:
      * control - {<OpenLayers.Control>}
@@ -1163,6 +1172,28 @@
         this.controls.push(control);
         this.addControlToMap(control, px);
     },
+    
+    /**
+     * APIMethod: addControls
+     * Add all of the passed over controls to the map. 
+     *     You can pass over an optional second array
+     *     with pixel-objects to position the controls.
+     *     The indices of the two arrays should match and
+     *     you can add null as pixel for those controls 
+     *     you want to be autopositioned.   
+     *     
+     * Parameters:
+     * controls - {Array(<OpenLayers.Control>)}
+     * pixels - {Array(<OpenLayers.Pixel>)}
+     */    
+    addControls: function (controls, pixels) {
+        var pxs = (arguments.length === 1) ? [] : pixels;
+        for (var i=0, len=controls.length; i<len; i++) {
+            var ctrl = controls[i];
+            var px = (pxs[i]) ? pxs[i] : null;
+            this.addControl( ctrl, px );
+        }
+    },
 
     /**
      * Method: addControlToMap
@@ -1192,6 +1223,9 @@
                 this.viewPortDiv.appendChild( div );
             }
         }
+        if(control.autoActivate) {
+            control.activate();
+        }
     },
     
     /**
@@ -1322,30 +1356,32 @@
      */
     updateSize: function() {
         // the div might have moved on the page, also
-        this.events.clearMouseCache();
         var newSize = this.getCurrentSize();
-        var oldSize = this.getSize();
-        if (oldSize == null) {
-            this.size = oldSize = newSize;
-        }
-        if (!newSize.equals(oldSize)) {
-            
-            // store the new size
-            this.size = newSize;
-
-            //notify layers of mapresize
-            for(var i=0, len=this.layers.length; i<len; i++) {
-                this.layers[i].onMapResize();                
+        if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) {
+            this.events.clearMouseCache();
+            var oldSize = this.getSize();
+            if (oldSize == null) {
+                this.size = oldSize = newSize;
             }
-
-            if (this.baseLayer != null) {
-                var center = new OpenLayers.Pixel(newSize.w /2, newSize.h / 2);
-                var centerLL = this.getLonLatFromViewPortPx(center);
-                var zoom = this.getZoom();
-                this.zoom = null;
-                this.setCenter(this.getCenter(), zoom);
+            if (!newSize.equals(oldSize)) {
+                
+                // store the new size
+                this.size = newSize;
+    
+                //notify layers of mapresize
+                for(var i=0, len=this.layers.length; i<len; i++) {
+                    this.layers[i].onMapResize();                
+                }
+    
+                var center = this.getCenter();
+    
+                if (this.baseLayer != null && center != null) {
+                    var zoom = this.getZoom();
+                    this.zoom = null;
+                    this.setCenter(center, zoom);
+                }
+    
             }
-
         }
     },
     
@@ -1361,11 +1397,9 @@
         var size = new OpenLayers.Size(this.div.clientWidth, 
                                        this.div.clientHeight);
 
-        // Workaround for the fact that hidden elements return 0 for size.
         if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
-            var dim = OpenLayers.Element.getDimensions(this.div);
-            size.w = dim.width;
-            size.h = dim.height;
+            size.w = this.div.offsetWidth;
+            size.h = this.div.offsetHeight;
         }
         if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
             size.w = parseInt(this.div.style.width);
@@ -1570,7 +1604,13 @@
     moveTo: function(lonlat, zoom, options) {
         if (!options) { 
             options = {};
-        }    
+        }
+        if (zoom != null) {
+            zoom = parseFloat(zoom);
+            if (!this.fractionalZoom) {
+                zoom = Math.round(zoom);
+            }
+        }
         // dragging is false by default
         var dragging = options.dragging;
         // forceZoomChange is false by default
@@ -1914,6 +1954,11 @@
         var resolution = null;
         if (this.baseLayer != null) {
             resolution = this.baseLayer.getResolution();
+        } else if(this.allOverlays === true && this.layers.length > 0) {
+            // while adding the 1st layer to the map in allOverlays mode,
+            // this.baseLayer is not set yet when we need the resolution
+            // for calculateInRange.
+            resolution = this.layers[0].getResolution();
         }
         return resolution;
     },
@@ -2237,6 +2282,39 @@
         px.y = Math.round(px.y);
         return px;
     },
+    
+    /**
+     * Method: getGeodesicPixelSize
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} The pixel to get the geodesic length for. If
+     *     not provided, the center pixel of the map viewport will be used.
+     * 
+     * Returns:
+     * {<OpenLayers.Size>} The geodesic size of the pixel in kilometers.
+     */
+    getGeodesicPixelSize: function(px) {
+        var lonlat = px ? this.getLonLatFromPixel(px) : (this.getCenter() ||
+            new OpenLayers.LonLat(0, 0));
+        var res = this.getResolution();
+        var left = lonlat.add(-res / 2, 0);
+        var right = lonlat.add(res / 2, 0);
+        var bottom = lonlat.add(0, -res / 2);
+        var top = lonlat.add(0, res / 2);
+        var dest = new OpenLayers.Projection("EPSG:4326");
+        var source = this.getProjectionObject() || dest;
+        if(!source.equals(dest)) {
+            left.transform(source, dest);
+            right.transform(source, dest);
+            bottom.transform(source, dest);
+            top.transform(source, dest);
+        }
+        
+        return new OpenLayers.Size(
+            OpenLayers.Util.distVincenty(left, right),
+            OpenLayers.Util.distVincenty(bottom, top)
+        );
+    },
 
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Marker/Box.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Marker/Box.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Marker/Box.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Marker.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Marker.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Marker.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -21,9 +22,9 @@
  * var markers = new OpenLayers.Layer.Markers( "Markers" );
  * map.addLayer(markers);
  *
- * var size = new OpenLayers.Size(10,17);
+ * var size = new OpenLayers.Size(21,25);
  * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
- * var icon = new OpenLayers.Icon('http://boston.openguides.org/markers/AQUA.png',size,offset);
+ * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
  * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
  * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
  *

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Popup/Anchored.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Popup/Anchored.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Popup/Anchored.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Popup/AnchoredBubble.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Popup/AnchoredBubble.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Popup/AnchoredBubble.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Popup/Framed.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Popup/Framed.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Popup/Framed.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Popup/FramedCloud.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Popup/FramedCloud.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Popup/FramedCloud.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -38,7 +39,7 @@
      * APIProperty: imageSize
      * {<OpenLayers.Size>}
      */
-    imageSize: new OpenLayers.Size(676, 736),
+    imageSize: new OpenLayers.Size(1276, 736),
 
     /**
      * APIProperty: isAlphaImage
@@ -71,7 +72,7 @@
                 { //top-right
                     size: new OpenLayers.Size(22, 'auto'),
                     anchor: new OpenLayers.Bounds(null, 50, 0, 0),
-                    position: new OpenLayers.Pixel(-638, 0)
+                    position: new OpenLayers.Pixel(-1238, 0)
                 },
                 { //bottom-left
                     size: new OpenLayers.Size('auto', 19),
@@ -81,7 +82,7 @@
                 { //bottom-right
                     size: new OpenLayers.Size(22, 18),
                     anchor: new OpenLayers.Bounds(null, 32, 0, null),
-                    position: new OpenLayers.Pixel(-638, -632)
+                    position: new OpenLayers.Pixel(-1238, -632)
                 },
                 { // stem
                     size: new OpenLayers.Size(81, 35),
@@ -102,7 +103,7 @@
                 { //top-right
                     size: new OpenLayers.Size(22, 'auto'),
                     anchor: new OpenLayers.Bounds(null, 50, 0, 0),
-                    position: new OpenLayers.Pixel(-638, 0)
+                    position: new OpenLayers.Pixel(-1238, 0)
                 },
                 { //bottom-left
                     size: new OpenLayers.Size('auto', 19),
@@ -112,7 +113,7 @@
                 { //bottom-right
                     size: new OpenLayers.Size(22, 19),
                     anchor: new OpenLayers.Bounds(null, 32, 0, null),
-                    position: new OpenLayers.Pixel(-638, -631)
+                    position: new OpenLayers.Pixel(-1238, -631)
                 },
                 { // stem
                     size: new OpenLayers.Size(81, 35),
@@ -133,7 +134,7 @@
                 { //top-right
                     size: new OpenLayers.Size(22, 'auto'),
                     anchor: new OpenLayers.Bounds(null, 21, 0, 32),
-                    position: new OpenLayers.Pixel(-638, 0)
+                    position: new OpenLayers.Pixel(-1238, 0)
                 },
                 { //bottom-left
                     size: new OpenLayers.Size('auto', 21),
@@ -143,7 +144,7 @@
                 { //bottom-right
                     size: new OpenLayers.Size(22, 21),
                     anchor: new OpenLayers.Bounds(null, 0, 0, null),
-                    position: new OpenLayers.Pixel(-638, -629)
+                    position: new OpenLayers.Pixel(-1238, -629)
                 },
                 { // stem
                     size: new OpenLayers.Size(81, 33),
@@ -164,7 +165,7 @@
                 { //top-right
                     size: new OpenLayers.Size(22, 'auto'),
                     anchor: new OpenLayers.Bounds(null, 21, 0, 32),
-                    position: new OpenLayers.Pixel(-638, 0)
+                    position: new OpenLayers.Pixel(-1238, 0)
                 },
                 { //bottom-left
                     size: new OpenLayers.Size('auto', 21),
@@ -174,7 +175,7 @@
                 { //bottom-right
                     size: new OpenLayers.Size(22, 21),
                     anchor: new OpenLayers.Bounds(null, 0, 0, null),
-                    position: new OpenLayers.Pixel(-638, -629)
+                    position: new OpenLayers.Pixel(-1238, -629)
                 },
                 { // stem
                     size: new OpenLayers.Size(81, 33),
@@ -195,7 +196,7 @@
      * APIProperty: maxSize
      * {<OpenLayers.Size>}
      */
-    maxSize: new OpenLayers.Size(600, 660),
+    maxSize: new OpenLayers.Size(1200, 660),
 
     /** 
      * Constructor: OpenLayers.Popup.FramedCloud

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Popup.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Popup.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Popup.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -336,7 +337,7 @@
         }
         
         //listen to movestart, moveend to disable overflow (FF bug)
-        if (!this.disableFirefoxOverflowHack && OpenLayers.Util.getBrowserName() == 'firefox') {
+        if (!this.disableFirefoxOverflowHack && OpenLayers.BROWSER_NAME == 'firefox') {
             this.map.events.register("movestart", this, function() {
                 var style = document.defaultView.getComputedStyle(
                     this.contentDiv, null
@@ -477,7 +478,7 @@
         //now if our browser is IE, we need to actually make the contents 
         // div itself bigger to take its own padding into effect. this makes 
         // me want to shoot someone, but so it goes.
-        if (OpenLayers.Util.getBrowserName() == "msie") {
+        if (OpenLayers.BROWSER_NAME == "msie") {
             this.contentSize.w += 
                 contentDivPadding.left + contentDivPadding.right;
             this.contentSize.h += 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Projection.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Projection.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Projection.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Util.js
@@ -25,6 +26,12 @@
      * {String}
      */
     projCode: null,
+    
+    /**
+     * Property: titleRegEx
+     * {RegEx} regular expression to strip the title from a proj4js definition
+     */
+    titleRegEx: /\+title=[^\+]*/,
 
     /**
      * Constructor: OpenLayers.Projection
@@ -91,11 +98,20 @@
      * {Boolean} The two projections are equivalent.
      */
     equals: function(projection) {
-        if (projection && projection.getCode) {
-            return this.getCode() == projection.getCode();
-        } else {
-            return false;
-        }    
+        var p = projection, equals = false;
+        if (p) {
+            if (window.Proj4js && this.proj.defData && p.proj.defData) {
+                equals = this.proj.defData.replace(this.titleRegEx, "") ==
+                    p.proj.defData.replace(this.titleRegEx, "");
+            } else if (p.getCode) {
+                var source = this.getCode(), target = p.getCode();
+                equals = source == target ||
+                    !!OpenLayers.Projection.transforms[source] &&
+                    OpenLayers.Projection.transforms[source][target] ===
+                        OpenLayers.Projection.nullTransform;
+            }
+        }
+        return equals;   
     },
 
     /* Method: destroy
@@ -175,3 +191,23 @@
     }
     return point;
 };
+
+/**
+ * APIFunction: nullTransform
+ * A null transformation - useful for defining projection aliases when
+ * proj4js is not available:
+ *
+ * (code)
+ * OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857",
+ *     OpenLayers.Layer.SphericalMercator.projectForward);
+ * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:3857",
+ *     OpenLayers.Layer.SphericalMercator.projectInverse);
+ * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913",
+ *     OpenLayers.Projection.nullTransform);
+ * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857",
+ *     OpenLayers.Projection.nullTransform);
+ * (end)
+ */
+OpenLayers.Projection.nullTransform = function(point) {
+    return point;
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/HTTP.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/HTTP.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/HTTP.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,10 +1,15 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/Protocol.js
  * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
  */
 
 /**
@@ -63,6 +68,17 @@
     readWithPOST: false,
 
     /**
+     * Property: wildcarded.
+     * {Boolean} If true percent signs are added around values
+     *     read from LIKE filters, for example if the protocol
+     *     read method is passed a LIKE filter whose property
+     *     is "foo" and whose value is "bar" the string
+     *     "foo__ilike=%bar%" will be sent in the query string;
+     *     defaults to false.
+     */
+    wildcarded: false,
+
+    /**
      * Constructor: OpenLayers.Protocol.HTTP
      * A class for giving layers generic HTTP protocol.
      *
@@ -79,6 +95,7 @@
      * scope - {Object}
      */
     initialize: function(options) {
+        options = options || {};
         this.params = {};
         this.headers = {};
         OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
@@ -95,23 +112,6 @@
     },
    
     /**
-     * Method: createCallback
-     * Returns a function that applies the given public method with resp and
-     *     options arguments.
-     *
-     * Parameters:
-     * method - {Function} The method to be applied by the callback.
-     * response - {<OpenLayers.Protocol.Response>} The protocol response object.
-     * options - {Object} Options sent to the protocol method (read, create,
-     *     update, or delete).
-     */
-    createCallback: function(method, response, options) {
-        return OpenLayers.Function.bind(function() {
-            method.apply(this, [response, options]);
-        }, this);
-    },
-
-    /**
      * APIMethod: read
      * Construct a request for reading new features.
      *
@@ -123,10 +123,8 @@
      * url - {String} Url for the request.
      * params - {Object} Parameters to get serialized as a query string.
      * headers - {Object} Headers to be set on the request.
-     * filter - {<OpenLayers.Filter.BBOX>} If a bbox filter is sent, it will be
-     *     serialized according to the OpenSearch Geo extension
-     *     (bbox=minx,miny,maxx,maxy).  Note that a BBOX filter as the child
-     *     of a logical filter will not be serialized.
+     * filter - {<OpenLayers.Filter>} Filter to get serialized as a
+     *     query string.
      * readWithPOST - {Boolean} If the request should be done with POST.
      *
      * Returns:
@@ -136,19 +134,17 @@
      *     is then populated with the the features received from the server.
      */
     read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
         options = OpenLayers.Util.applyDefaults(options, this.options);
+        options.params = OpenLayers.Util.applyDefaults(
+            options.params, this.options.params);
+        if(options.filter) {
+            options.params = this.filterToParams(
+                options.filter, options.params);
+        }
         var readWithPOST = (options.readWithPOST !== undefined) ?
                            options.readWithPOST : this.readWithPOST;
         var resp = new OpenLayers.Protocol.Response({requestType: "read"});
-
-        if(options.filter && options.filter instanceof OpenLayers.Filter.Spatial) {
-            if(options.filter.type == OpenLayers.Filter.Spatial.BBOX) {
-                options.params = OpenLayers.Util.extend(options.params, {
-                    bbox: options.filter.value.toArray()
-                });
-            }
-        }
-
         if(readWithPOST) {
             resp.priv = OpenLayers.Request.POST({
                 url: options.url,
@@ -166,7 +162,6 @@
                 headers: options.headers
             });
         }
-
         return resp;
     },
 
@@ -183,8 +178,123 @@
     handleRead: function(resp, options) {
         this.handleResponse(resp, options);
     },
-    
+
     /**
+     * Method: filterToParams
+     * Convert an <OpenLayers.Filter> object to parameters.
+     *
+     * Parameters:
+     * filter - {OpenLayers.Filter} filter to convert.
+     * params - {Object} The parameters object.
+     *
+     * Returns:
+     * {Object} The resulting parameters object.
+     */
+    filterToParams: function(filter, params) {
+        params = params || {};
+        var className = filter.CLASS_NAME;
+        var filterType = className.substring(className.lastIndexOf(".") + 1);
+        switch(filterType) {
+            case "Spatial":
+                switch(filter.type) {
+                    case OpenLayers.Filter.Spatial.BBOX:
+                        params.bbox = filter.value.toArray();
+                        break;
+                    case OpenLayers.Filter.Spatial.DWITHIN:
+                        params.tolerance = filter.distance;
+                        // no break here
+                    case OpenLayers.Filter.Spatial.WITHIN:
+                        params.lon = filter.value.x;
+                        params.lat = filter.value.y;
+                        break;
+                    default:
+                        OpenLayers.Console.warn(
+                            "Unknown spatial filter type " + filter.type);
+                }
+                break;
+            case "Comparison":
+                var op = OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR[filter.type];
+                if(op !== undefined) {
+                    var value = filter.value;
+                    if(filter.type == OpenLayers.Filter.Comparison.LIKE) {
+                        value = this.regex2value(value);
+                        if(this.wildcarded) {
+                            value = "%" + value + "%";
+                        }
+                    }
+                    params[filter.property + "__" + op] = value;
+                    params.queryable = params.queryable || [];
+                    params.queryable.push(filter.property);
+                } else {
+                    OpenLayers.Console.warn(
+                        "Unknown comparison filter type " + filter.type);
+                }
+                break;
+            case "Logical":
+                if(filter.type === OpenLayers.Filter.Logical.AND) {
+                    for(var i=0,len=filter.filters.length; i<len; i++) {
+                        params = this.filterToParams(filter.filters[i], params);
+                    }
+                } else {
+                    OpenLayers.Console.warn(
+                        "Unsupported logical filter type " + filter.type);
+                }
+                break;
+            default:
+                OpenLayers.Console.warn("Unknown filter type " + filterType);
+        }
+        return params;
+    },
+
+    /**
+     * Method: regex2value
+     * Convert the value from a regular expression string to a LIKE/ILIKE
+     * string known to the web service.
+     *
+     * Parameters:
+     * value - {String} The regex string.
+     *
+     * Returns:
+     * {String} The converted string.
+     */
+    regex2value: function(value) {
+
+        // highly sensitive!! Do not change this without running the
+        // Protocol/HTTP.html unit tests
+
+        // convert % to \%
+        value = value.replace(/%/g, "\\%");
+
+        // convert \\. to \\_ (\\.* occurences converted later)
+        value = value.replace(/\\\\\.(\*)?/g, function($0, $1) {
+            return $1 ? $0 : "\\\\_";
+        });
+
+        // convert \\.* to \\%
+        value = value.replace(/\\\\\.\*/g, "\\\\%");
+
+        // convert . to _ (\. and .* occurences converted later)
+        value = value.replace(/(\\)?\.(\*)?/g, function($0, $1, $2) {
+            return $1 || $2 ? $0 : "_";
+        });
+
+        // convert .* to % (\.* occurnces converted later)
+        value = value.replace(/(\\)?\.\*/g, function($0, $1) {
+            return $1 ? $0 : "%";
+        });
+
+        // convert \. to .
+        value = value.replace(/\\\./g, ".");
+
+        // replace \* with * (watching out for \\*)
+        value = value.replace(/(\\)?\\\*/g, function($0, $1) {
+            return $1 ? $0 : "*";
+        });
+
+        return value;
+    },
+
+    /**
      * APIMethod: create
      * Construct a request for writing newly created features.
      *
@@ -250,7 +360,10 @@
      *     the feature received from the server.
      */
     update: function(feature, options) {
-        var url = options.url || feature.url || this.options.url;
+        options = options || {};
+        var url = options.url ||
+                  feature.url ||
+                  this.options.url + "/" + feature.fid;
         options = OpenLayers.Util.applyDefaults(options, this.options);
 
         var resp = new OpenLayers.Protocol.Response({
@@ -298,7 +411,10 @@
      *     completes.
      */
     "delete": function(feature, options) {
-        var url = options.url || feature.url || this.options.url;
+        options = options || {};
+        var url = options.url ||
+                  feature.url ||
+                  this.options.url + "/" + feature.fid;
         options = OpenLayers.Util.applyDefaults(options, this.options);
 
         var resp = new OpenLayers.Protocol.Response({
@@ -519,3 +635,21 @@
 
     CLASS_NAME: "OpenLayers.Protocol.HTTP" 
 });
+
+/**
+ * Property: OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR
+ * {Object} A private class-level property mapping the
+ *     OpenLayers.Filter.Comparison types to the operation
+ *     strings of the protocol.
+ */
+(function() {
+    var o = OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR = {};
+    o[OpenLayers.Filter.Comparison.EQUAL_TO]                 = "eq";
+    o[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]             = "ne";
+    o[OpenLayers.Filter.Comparison.LESS_THAN]                = "lt";
+    o[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]    = "lte";
+    o[OpenLayers.Filter.Comparison.GREATER_THAN]             = "gt";
+    o[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO] = "gte";
+    o[OpenLayers.Filter.Comparison.LIKE]                     = "ilike";
+})();
+

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Protocol/SOS/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,132 +0,0 @@
-/* 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/Protocol/SOS.js
- * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
- */
-
-/**
- * Class: OpenLayers.Protocol.SOS.v1_0_0
- * An SOS v1.0.0 Protocol for vector layers.  Create a new instance with the
- *     <OpenLayers.Protocol.SOS.v1_0_0> constructor.
- *
- * Inherits from:
- *  - <OpenLayers.Protocol>
- */
- OpenLayers.Protocol.SOS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol, {
-
-    /**
-     * APIProperty: fois
-     * {Array(String)} Array of features of interest (foi)
-     */
-    fois: null,
-
-    /**
-     * Property: formatOptions
-     * {Object} Optional options for the format.  If a format is not provided,
-     *     this property can be used to extend the default format options.
-     */
-    formatOptions: null,
-   
-    /**
-     * Constructor: OpenLayers.Protocol.SOS
-     * A class for giving layers an SOS protocol.
-     *
-     * Parameters:
-     * options - {Object} Optional object whose properties will be set on the
-     *     instance.
-     * Valid options properties:
-     * url - {String} URL to send requests to (required).
-     * fois - {Array} The features of interest (required).
-     */
-    initialize: function(options) {
-        OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
-        if(!options.format) {
-            this.format = new OpenLayers.Format.SOSGetFeatureOfInterest(
-                this.formatOptions);
-        }
-    },
-   
-    /**
-     * APIMethod: destroy
-     * Clean up the protocol.
-     */
-    destroy: function() {
-        if(this.options && !this.options.format) {
-            this.format.destroy();
-        }
-        this.format = null;
-        OpenLayers.Protocol.prototype.destroy.apply(this);
-    },
-
-    /**
-     * APIMethod: read
-     * Construct a request for reading new sensor positions. This is done by
-     *     issuing one GetFeatureOfInterest request.
-     */
-    read: function(options) {
-        options = OpenLayers.Util.extend({}, options);
-        OpenLayers.Util.applyDefaults(options, this.options || {});
-        var response = new OpenLayers.Protocol.Response({requestType: "read"});
-        var format = this.format;
-        var data = OpenLayers.Format.XML.prototype.write.apply(format,
-            [format.writeNode("sos:GetFeatureOfInterest", {fois: this.fois})]
-        );
-        response.priv = OpenLayers.Request.POST({
-            url: options.url,
-            callback: this.createCallback(this.handleRead, response, options),
-            data: data
-        });
-        return response;
-    },
-   
-    /**
-     * Method: handleRead
-     * Deal with response from the read request.
-     *
-     * Parameters:
-     * response - {<OpenLayers.Protocol.Response>} The response object to pass
-     *     to the user callback.
-     * options - {Object} The user options passed to the read call.
-     */
-    handleRead: function(response, options) {
-        if(options.callback) {
-            var request = response.priv;
-            if(request.status >= 200 && request.status < 300) {
-                // success
-                response.features = this.parseFeatures(request);
-                response.code = OpenLayers.Protocol.Response.SUCCESS;
-            } else {
-                // failure
-                response.code = OpenLayers.Protocol.Response.FAILURE;
-            }
-            options.callback.call(options.scope, response);
-        }
-    },
-
-    /**
-     * Method: parseFeatures
-     * Read HTTP response body and return features
-     *
-     * Parameters:
-     * request - {XMLHttpRequest} The request object
-     *
-     * Returns:
-     * {Array({<OpenLayers.Feature.Vector>})} Array of features
-     */
-    parseFeatures: function(request) {
-        var doc = request.responseXML;
-        if(!doc || !doc.documentElement) {
-            doc = request.responseText;
-        }
-        if(!doc || doc.length <= 0) {
-            return null;
-        }
-        return this.format.read(doc);
-    },
-
-    CLASS_NAME: "OpenLayers.Protocol.SOS.v1_0_0"
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Protocol/SOS/v1_0_0.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,132 @@
+/* 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/Protocol/SOS.js
+ * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.SOS.v1_0_0
+ * An SOS v1.0.0 Protocol for vector layers.  Create a new instance with the
+ *     <OpenLayers.Protocol.SOS.v1_0_0> constructor.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol>
+ */
+ OpenLayers.Protocol.SOS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol, {
+
+    /**
+     * APIProperty: fois
+     * {Array(String)} Array of features of interest (foi)
+     */
+    fois: null,
+
+    /**
+     * Property: formatOptions
+     * {Object} Optional options for the format.  If a format is not provided,
+     *     this property can be used to extend the default format options.
+     */
+    formatOptions: null,
+   
+    /**
+     * Constructor: OpenLayers.Protocol.SOS
+     * A class for giving layers an SOS protocol.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     * Valid options properties:
+     * url - {String} URL to send requests to (required).
+     * fois - {Array} The features of interest (required).
+     */
+    initialize: function(options) {
+        OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
+        if(!options.format) {
+            this.format = new OpenLayers.Format.SOSGetFeatureOfInterest(
+                this.formatOptions);
+        }
+    },
+   
+    /**
+     * APIMethod: destroy
+     * Clean up the protocol.
+     */
+    destroy: function() {
+        if(this.options && !this.options.format) {
+            this.format.destroy();
+        }
+        this.format = null;
+        OpenLayers.Protocol.prototype.destroy.apply(this);
+    },
+
+    /**
+     * APIMethod: read
+     * Construct a request for reading new sensor positions. This is done by
+     *     issuing one GetFeatureOfInterest request.
+     */
+    read: function(options) {
+        options = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.applyDefaults(options, this.options || {});
+        var response = new OpenLayers.Protocol.Response({requestType: "read"});
+        var format = this.format;
+        var data = OpenLayers.Format.XML.prototype.write.apply(format,
+            [format.writeNode("sos:GetFeatureOfInterest", {fois: this.fois})]
+        );
+        response.priv = OpenLayers.Request.POST({
+            url: options.url,
+            callback: this.createCallback(this.handleRead, response, options),
+            data: data
+        });
+        return response;
+    },
+   
+    /**
+     * Method: handleRead
+     * Deal with response from the read request.
+     *
+     * Parameters:
+     * response - {<OpenLayers.Protocol.Response>} The response object to pass
+     *     to the user callback.
+     * options - {Object} The user options passed to the read call.
+     */
+    handleRead: function(response, options) {
+        if(options.callback) {
+            var request = response.priv;
+            if(request.status >= 200 && request.status < 300) {
+                // success
+                response.features = this.parseFeatures(request);
+                response.code = OpenLayers.Protocol.Response.SUCCESS;
+            } else {
+                // failure
+                response.code = OpenLayers.Protocol.Response.FAILURE;
+            }
+            options.callback.call(options.scope, response);
+        }
+    },
+
+    /**
+     * Method: parseFeatures
+     * Read HTTP response body and return features
+     *
+     * Parameters:
+     * request - {XMLHttpRequest} The request object
+     *
+     * Returns:
+     * {Array({<OpenLayers.Feature.Vector>})} Array of features
+     */
+    parseFeatures: function(request) {
+        var doc = request.responseXML;
+        if(!doc || !doc.documentElement) {
+            doc = request.responseText;
+        }
+        if(!doc || doc.length <= 0) {
+            return null;
+        }
+        return this.format.read(doc);
+    },
+
+    CLASS_NAME: "OpenLayers.Protocol.SOS.v1_0_0"
+});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Protocol/SOS.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SOS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,33 @@
+/* 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/Protocol.js
+ */
+
+/**
+ * Function: OpenLayers.Protocol.SOS
+ * Used to create a versioned SOS protocol.  Default version is 1.0.0.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol>} An SOS protocol for the given version.
+ */
+OpenLayers.Protocol.SOS = function(options) {
+    options = OpenLayers.Util.applyDefaults(
+        options, OpenLayers.Protocol.SOS.DEFAULTS
+    );
+    var cls = OpenLayers.Protocol.SOS["v"+options.version.replace(/\./g, "_")];
+    if(!cls) {
+        throw "Unsupported SOS version: " + options.version;
+    }
+    return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Protocol.SOS.DEFAULTS
+ */
+OpenLayers.Protocol.SOS.DEFAULTS = {
+    "version": "1.0.0"
+};

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL/Gears.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL/Gears.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL/Gears.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -154,6 +155,7 @@
      *      object.
      */
     read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
         options = OpenLayers.Util.applyDefaults(options, this.options);
 
         var feature, features = [];

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/SQL.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Protocol/WFS.js
  */
@@ -64,8 +69,23 @@
      *     this property can be used to extend the default format options.
      */
     formatOptions: null,
+
+    /** 
+     * Property: readFormat 
+     * {<OpenLayers.Format>} For WFS requests it is possible to get a  
+     *     different output format than GML. In that case, we cannot parse  
+     *     the response with the default format (WFST) and we need a different 
+     *     format for reading. 
+     */ 
+    readFormat: null,     
     
     /**
+     * Property: readOptions
+     * {Object} Optional object to pass to format's read.
+     */
+    readOptions: null,
+    
+    /**
      * Constructor: OpenLayers.Protocol.WFS
      * A class for giving layers WFS protocol.
      *
@@ -96,7 +116,7 @@
                 schema: this.schema
             }, this.formatOptions));
         }
-        if(!this.featureNS) {
+        if(!this.featureNS && this.featurePrefix) {
             // featureNS autodetection
             var readNode = this.format.readNode;
             this.format.readNode = function(node, obj) {
@@ -105,7 +125,7 @@
                     this.setNamespace("feature", this.featureNS);
                 }
                 return readNode.apply(this, arguments);
-            }
+            };
         }
     },
     
@@ -122,23 +142,6 @@
     },
 
     /**
-     * Method: createCallback
-     * Returns a function that applies the given public method with resp and
-     *     options arguments.
-     *
-     * Parameters:
-     * method - {Function} The method to be applied by the callback.
-     * response - {<OpenLayers.Protocol.Response>} The protocol response object.
-     * options - {Object} Options sent to the protocol method (read, create,
-     *     update, or delete).
-     */
-    createCallback: function(method, response, options) {
-        return OpenLayers.Function.bind(function() {
-            method.apply(this, [response, options]);
-        }, this);
-    },
-
-    /**
      * Method: read
      * Construct a request for reading new features.  Since WFS splits the
      *     basic CRUD operations into GetFeature requests (for read) and
@@ -147,6 +150,7 @@
      *     responses).
      */
     read: function(options) {
+        OpenLayers.Protocol.prototype.read.apply(this, arguments);
         options = OpenLayers.Util.extend({}, options);
         OpenLayers.Util.applyDefaults(options, this.options || {});
         var response = new OpenLayers.Protocol.Response({requestType: "read"});
@@ -180,28 +184,36 @@
             var request = response.priv;
             if(request.status >= 200 && request.status < 300) {
                 // success
-                response.features = this.parseFeatures(request);
+                if (this.readOptions && this.readOptions.output == "object") {
+                    OpenLayers.Util.extend(response, 
+                        this.parseResponse(request, this.readOptions));
+                } else {
+                    response.features = this.parseResponse(request);
+                }
                 response.code = OpenLayers.Protocol.Response.SUCCESS;
             } else {
                 // failure
                 response.code = OpenLayers.Protocol.Response.FAILURE;
             }
             options.callback.call(options.scope, response);
-        }; 
+        }
     },
 
     /**
-     * Method: parseFeatures
+     * Method: parseResponse
      * Read HTTP response body and return features
      *
      * Parameters:
      * request - {XMLHttpRequest} The request object
+     * options - {Object} Optional object to pass to format's read
      *
      * Returns:
-     * {Array({<OpenLayers.Feature.Vector>})} or
-     *     {<OpenLayers.Feature.Vector>} Array of features or a single feature.
+     * {Object} or {Array({<OpenLayers.Feature.Vector>})} or
+     *     {<OpenLayers.Feature.Vector>} 
+     * An object with a features property, an array of features or a single 
+     * feature.
      */
-    parseFeatures: function(request) {
+    parseResponse: function(request, options) {
         var doc = request.responseXML;
         if(!doc || !doc.documentElement) {
             doc = request.responseText;
@@ -209,7 +221,8 @@
         if(!doc || doc.length <= 0) {
             return null;
         }
-        return this.format.read(doc);
+        return (this.readFormat !== null) ? this.readFormat.read(doc) : 
+            this.format.read(doc, options);
     },
 
     /**
@@ -290,9 +303,9 @@
         });    
         
         var root = this.format.createElementNSPlus("wfs:Transaction", {
-        	attributes: {
-       	        service: "WFS",
-        	    version: this.version
+            attributes: {
+                service: "WFS",
+                version: this.version
             }
         });
         

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_0_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Protocol/WFS/v1.js
  * @requires OpenLayers/Format/WFST/v1_0_0.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_1_0.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_1_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS/v1_1_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,8 @@
+/* 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/Protocol/WFS/v1.js
  * @requires OpenLayers/Format/WFST/v1_1_0.js

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol/WFS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Protocol.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Protocol.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Protocol.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -30,6 +31,12 @@
     autoDestroy: true,
    
     /**
+     * Property: defaultFilter
+     * {OpenLayers.Filter} Optional default filter to read requests
+     */
+    defaultFilter: null,
+    
+    /**
      * Constructor: OpenLayers.Protocol
      * Abstract class for vector protocols.  Create instances of a subclass.
      *
@@ -44,6 +51,26 @@
     },
 
     /**
+     * Method: mergeWithDefaultFilter
+     * Merge filter passed to the read method with the default one
+     *
+     * Parameters:
+     * filter - {OpenLayers.Filter}
+     */
+    mergeWithDefaultFilter: function(filter) {
+        var merged;
+        if (filter && this.defaultFilter) {
+            merged = new OpenLayers.Filter.Logical({
+                type: OpenLayers.Filter.Logical.AND,
+                filters: [this.defaultFilter, filter]
+            });
+        } else {
+            merged = filter || this.defaultFilter || undefined;
+        }
+        return merged;
+    },
+
+    /**
      * APIMethod: destroy
      * Clean up the protocol.
      */
@@ -64,7 +91,9 @@
      * object, the same object will be passed to the callback function passed
      * if one exists in the options object.
      */
-    read: function() {
+    read: function(options) {
+        options = options || {};
+        options.filter = this.mergeWithDefaultFilter(options.filter);
     },
     
     
@@ -150,6 +179,22 @@
     abort: function(response) {
     },
    
+    /**
+     * Method: createCallback
+     * Returns a function that applies the given public method with resp and
+     *     options arguments.
+     *
+     * Parameters:
+     * method - {Function} The method to be applied by the callback.
+     * response - {<OpenLayers.Protocol.Response>} The protocol response object.
+     * options - {Object} Options sent to the protocol method
+     */
+    createCallback: function(method, response, options) {
+        return OpenLayers.Function.bind(function() {
+            method.apply(this, [response, options]);
+        }, this);
+    },
+   
     CLASS_NAME: "OpenLayers.Protocol" 
 });
 


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Protocol.js
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Canvas.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Canvas.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Canvas.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -28,14 +29,6 @@
     features: null, 
    
     /**
-     * Property: geometryMap
-     * {Object} Geometry -> Feature lookup table. Used by eraseGeometry to
-     *     lookup features to remove from our internal table (this.features)
-     *     when erasing geoms.
-     */
-    geometryMap: null,
- 
-    /**
      * Constructor: OpenLayers.Renderer.Canvas
      *
      * Parameters:
@@ -47,7 +40,6 @@
         this.container.appendChild(this.root);
         this.canvas = this.root.getContext("2d");
         this.features = {};
-        this.geometryMap = {};
     },
     
     /** 
@@ -58,9 +50,10 @@
      * 
      * Parameters:
      * geometry - {<OpenLayers.Geometry>}
+     * featureId - {String}
      */
-    eraseGeometry: function(geometry) {
-        this.eraseFeatures(this.features[this.geometryMap[geometry.id]][0]);
+    eraseGeometry: function(geometry, featureId) {
+        this.eraseFeatures(this.features[featureId][0]);
     },
 
     /**
@@ -75,22 +68,6 @@
     },    
     
     /**
-     * Method: setExtent
-     * Set the visible part of the layer.
-     *
-     * Resolution has probably changed, so we nullify the resolution 
-     * cache (this.resolution), then redraw. 
-     *
-     * Parameters:
-     * extent - {<OpenLayers.Bounds>} 
-     */
-    setExtent: function(extent) {
-        this.extent = extent.clone();
-        this.resolution = null;
-        this.redraw();
-    },
-    
-    /**
      * Method: setSize
      * Sets the size of the drawing surface.
      *
@@ -118,20 +95,10 @@
      * style - {<Object>} 
      */
     drawFeature: function(feature, style) {
-        if(style == null) {
-            style = feature.style;
-        }
-        style = OpenLayers.Util.extend({
-          'fillColor': '#000000',
-          'strokeColor': '#000000',
-          'strokeWidth': 2,
-          'fillOpacity': 1,
-          'strokeOpacity': 1
-        }, style);  
+        style = style || feature.style;
+        style = this.applyDefaultSymbolizer(style);  
+        
         this.features[feature.id] = [feature, style]; 
-        if (feature.geometry) { 
-            this.geometryMap[feature.geometry.id] = feature.id;
-        }    
         this.redraw();
     },
 
@@ -155,7 +122,7 @@
                 this.drawGeometry(geometry.components[i], style);
             }
             return;
-        };
+        }
         switch (geometry.CLASS_NAME) {
             case "OpenLayers.Geometry.Point":
                 this.drawPoint(geometry, style);
@@ -184,7 +151,6 @@
      */ 
     drawExternalGraphic: function(pt, style) {
        var img = new Image();
-       img.src = style.externalGraphic;
        
        if(style.graphicTitle) {
            img.title=style.graphicTitle;           
@@ -198,19 +164,21 @@
            style.graphicXOffset : -(0.5 * width);
        var yOffset = (style.graphicYOffset != undefined) ?
            style.graphicYOffset : -(0.5 * height);
-       var opacity = style.graphicOpacity || style.fillOpacity;
        
        var context = { img: img, 
                        x: (pt[0]+xOffset), 
                        y: (pt[1]+yOffset), 
                        width: width, 
                        height: height, 
+                       opacity: style.graphicOpacity || style.fillOpacity,
                        canvas: this.canvas };
 
        img.onload = OpenLayers.Function.bind( function() {
+           this.canvas.globalAlpha = this.opacity;
            this.canvas.drawImage(this.img, this.x, 
                                  this.y, this.width, this.height);
-       }, context);   
+       }, context);
+       img.src = style.externalGraphic;
     },
 
     /**
@@ -253,14 +221,14 @@
                 if(style.fill !== false) {
                     this.setCanvasStyle("fill", style);
                     this.canvas.beginPath();
-                    this.canvas.arc(pt[0], pt[1], 6, 0, Math.PI*2, true);
+                    this.canvas.arc(pt[0], pt[1], style.pointRadius, 0, Math.PI*2, true);
                     this.canvas.fill();
                 }
                 
                 if(style.stroke !== false) {
                     this.setCanvasStyle("stroke", style);
                     this.canvas.beginPath();
-                    this.canvas.arc(pt[0], pt[1], 6, 0, Math.PI*2, true);
+                    this.canvas.arc(pt[0], pt[1], style.pointRadius, 0, Math.PI*2, true);
                     this.canvas.stroke();
                     this.setCanvasStyle("reset");
                 }
@@ -313,7 +281,6 @@
         }
         
         if(style.stroke !== false) {
-            var oldWidth = this.canvas.lineWidth; 
             this.setCanvasStyle("stroke", style);
             this.canvas.beginPath();
             var start = this.getLocalXY(geometry.components[0]);
@@ -365,13 +332,13 @@
         
         this.setCanvasStyle("reset");
         this.canvas.fillStyle = style.fontColor;
-        this.canvas.globalAlpha = 1;
+        this.canvas.globalAlpha = style.fontOpacity || 1.0;
         var fontStyle = style.fontWeight + " " + style.fontSize + " " + style.fontFamily;
         if (this.canvas.fillText) {
             // HTML5
             var labelAlign =
                 OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] ||
-                "middle";
+                "center";
             this.canvas.font = fontStyle;
             this.canvas.textAlign = labelAlign;
             this.canvas.fillText(style.label, pt[0], pt[1]);
@@ -412,14 +379,14 @@
         var y = ((extent.top / resolution) - point.y / resolution);
         return [x, y];
     },
-        
+
     /**
      * Method: clear
      * Clear all vectors from the renderer.
-     * virtual function.
      */    
     clear: function() {
         this.canvas.clearRect(0, 0, this.root.width, this.root.height);
+        this.features = {};
     },
 
     /**
@@ -477,7 +444,7 @@
      */
     redraw: function() {
         if (!this.locked) {
-            this.clear();
+            this.canvas.clearRect(0, 0, this.root.width, this.root.height);
             var labelMap = [];
             var feature, style;
             for (var id in this.features) {
@@ -491,7 +458,7 @@
                 }
             }
             var item;
-            for (var i=0; len=labelMap.length, i<len; ++i) {
+            for (var i=0, len=labelMap.length; i<len; ++i) {
                 item = labelMap[i];
                 this.drawText(item[0].geometry.getCentroid(), item[1]);
             }

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Elements.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Elements.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Renderer/Elements.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -109,7 +110,7 @@
         // If the new node should be before another in the index
         // order, return the node before which we have to insert the new one;
         // else, return null to indicate that the new node can be appended.
-	return this.getNextElement(rightIndex);
+        return this.getNextElement(rightIndex);
     },
     
     /**
@@ -198,7 +199,7 @@
             this.maxZIndex = zIndex;
         }
     },
-	
+
     /**
      * APIMethod: getNextElement
      * Get the next element in the order stack.
@@ -211,17 +212,17 @@
      *     null.
      */
     getNextElement: function(index) {
-		var nextIndex = index + 1;
-        if (nextIndex < this.order.length){
-			var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
-			if (nextElement == undefined){
-			  nextElement = this.getNextElement(nextIndex);
-			}
-			return nextElement;
-		} else {
-			return null;
-		} 
-    },	
+        var nextIndex = index + 1;
+        if (nextIndex < this.order.length) {
+            var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
+            if (nextElement == undefined) {
+                nextElement = this.getNextElement(nextIndex);
+            }
+            return nextElement;
+        } else {
+            return null;
+        } 
+    },
     
     CLASS_NAME: "OpenLayers.ElementsIndexer"
 });
@@ -318,12 +319,9 @@
             nextNode
         );
         
-        if (nextNode && returnVal == 0) {
-            var newLat = newNode._geometry.getBounds().bottom;
-            var nextLat = nextNode._geometry.getBounds().bottom;
-            
-            var result = nextLat - newLat;
-            returnVal = (result ==0) ? 1 : result;
+        if (nextNode && returnVal === 0) {            
+            var result = nextNode._boundsBottom - newNode._boundsBottom;
+            returnVal = (result === 0) ? 1 : result;
         }
         
         return returnVal;       
@@ -398,18 +396,6 @@
     LABEL_ID_SUFFIX: "_label",
     
     /**
-     * Property: minimumSymbolizer
-     * {Object}
-     */
-    minimumSymbolizer: {
-        strokeLinecap: "round",
-        strokeOpacity: 1,
-        strokeDashstyle: "solid",
-        fillOpacity: 1,
-        pointRadius: 0
-    },
-    
-    /**
      * Constructor: OpenLayers.Renderer.Elements
      * 
      * Parameters:
@@ -457,14 +443,17 @@
      * Remove all the elements from the root
      */    
     clear: function() {
-        if (this.vectorRoot) {
-            while (this.vectorRoot.childNodes.length > 0) {
-                this.vectorRoot.removeChild(this.vectorRoot.firstChild);
+        var child;
+        var root = this.vectorRoot;
+        if (root) {
+            while (child = root.firstChild) {
+                root.removeChild(child);
             }
         }
-        if (this.textRoot) {
-            while (this.textRoot.childNodes.length > 0) {
-                this.textRoot.removeChild(this.textRoot.firstChild);
+        root = this.textRoot;
+        if (root) {
+            while (child = root.firstChild) {
+                root.removeChild(child);
             }
         }
         if (this.indexer) {
@@ -520,10 +509,13 @@
         };
 
         rendered = false;
+        var removeBackground = false;
         if (style.display != "none") {
             if (style.backgroundGraphic) {
                 this.redrawBackgroundNode(geometry.id, geometry, style,
                     featureId);
+            } else {
+                removeBackground = true;
             }
             rendered = this.redrawNode(geometry.id, geometry, style,
                 featureId);
@@ -532,12 +524,18 @@
             var node = document.getElementById(geometry.id);
             if (node) {
                 if (node._style.backgroundGraphic) {
-                    node.parentNode.removeChild(document.getElementById(
-                        geometry.id + this.BACKGROUND_ID_SUFFIX));
+                    removeBackground = true;
                 }
                 node.parentNode.removeChild(node);
             }
         }
+        if (removeBackground) {
+            var node = document.getElementById(
+                geometry.id + this.BACKGROUND_ID_SUFFIX);
+            if (node) {
+                node.parentNode.removeChild(node);
+            }
+        }
         return rendered;
     },
     
@@ -555,12 +553,13 @@
      *     the geometry could not be drawn, false otherwise
      */
     redrawNode: function(id, geometry, style, featureId) {
+        style = this.applyDefaultSymbolizer(style);
         // Get the node if it's already on the map.
         var node = this.nodeFactory(id, this.getNodeType(geometry, style));
         
         // Set the data for the node, then draw it.
         node._featureId = featureId;
-        node._geometry = geometry;
+        node._boundsBottom = geometry.getBounds().bottom;
         node._geometryClass = geometry.CLASS_NAME;
         node._style = style;
 
@@ -658,7 +657,6 @@
      */
     drawGeometryNode: function(node, geometry, style) {
         style = style || node._style;
-        OpenLayers.Util.applyDefaults(style, this.minimumSymbolizer);
 
         var options = {
             'isFilled': style.fill === undefined ?
@@ -697,7 +695,6 @@
                 break;
         }
 
-        node._style = style; 
         node._options = options; 
 
         //set style
@@ -871,14 +868,15 @@
      * 
      * Parameters:
      * geometry - {<OpenLayers.Geometry>}
+     * featureId - {String}
      */
-    eraseGeometry: function(geometry) {
+    eraseGeometry: function(geometry, featureId) {
         if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") ||
             (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") ||
             (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") ||
             (geometry.CLASS_NAME == "OpenLayers.Geometry.Collection")) {
             for (var i=0, len=geometry.components.length; i<len; i++) {
-                this.eraseGeometry(geometry.components[i]);
+                this.eraseGeometry(geometry.components[i], featureId);
             }
         } else {    
             var element = OpenLayers.Util.getElement(geometry.id);

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Renderer/SVG.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Renderer/SVG.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Renderer/SVG.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -41,16 +42,20 @@
     translationParameters: null,
     
     /**
-     * Property: symbolSize
-     * {Object} Cache for symbol sizes according to their svg coordinate space
+     * Property: symbolMetrics
+     * {Object} Cache for symbol metrics according to their svg coordinate
+     *     space. This is an object keyed by the symbol's id, and values are
+     *     an array of [width, centerX, centerY].
      */
-    symbolSize: {},
+    symbolMetrics: null,
     
     /**
-     * Property: isGecko
-     * {Boolean}
+     * Property: supportUse
+     * {Boolean} true if defs/use is supported - known to not work as expected
+     * at least in some applewebkit/5* builds.
+     * See https://bugs.webkit.org/show_bug.cgi?id=33322
      */
-    isGecko: null,
+    supportUse: null,
 
     /**
      * Constructor: OpenLayers.Renderer.SVG
@@ -65,7 +70,9 @@
         OpenLayers.Renderer.Elements.prototype.initialize.apply(this, 
                                                                 arguments);
         this.translationParameters = {x: 0, y: 0};
-        this.isGecko = (navigator.userAgent.toLowerCase().indexOf("gecko/") != -1);
+        this.supportUse = (navigator.userAgent.toLowerCase().indexOf("applewebkit/5") == -1);
+        
+        this.symbolMetrics = {};
     },
 
     /**
@@ -208,7 +215,7 @@
                 if (style.externalGraphic) {
                     nodeType = "image";
                 } else if (this.isComplexSymbol(style.graphicName)) {
-                    nodeType = "use";
+                    nodeType = this.supportUse === false ? "svg" : "use";
                 } else {
                     nodeType = "circle";
                 }
@@ -260,7 +267,7 @@
             } else if (style.externalGraphic) {
                 pos = this.getPosition(node);
                 
-        		if (style.graphicTitle) {
+                if (style.graphicTitle) {
                     node.setAttributeNS(null, "title", style.graphicTitle);
                 }
                 if (style.graphicWidth && style.graphicHeight) {
@@ -288,9 +295,8 @@
                 var offset = style.pointRadius * 3;
                 var size = offset * 2;
                 var id = this.importSymbol(style.graphicName);
-                var href = "#" + id;
                 pos = this.getPosition(node);
-                widthFactor = this.symbolSize[id] / size;
+                widthFactor = this.symbolMetrics[id][0] * 3 / size;
                 
                 // remove the node from the dom before we modify it. This
                 // prevents various rendering issues in Safari and FF
@@ -300,7 +306,17 @@
                     parent.removeChild(node);
                 }
                 
-                node.setAttributeNS(this.xlinkns, "href", href);
+                if(this.supportUse === false) {
+                    // workaround for webkit versions that cannot do defs/use
+                    // (see https://bugs.webkit.org/show_bug.cgi?id=33322):
+                    // copy the symbol instead of referencing it
+                    var src = document.getElementById(id);
+                    node.firstChild && node.removeChild(node.firstChild);
+                    node.appendChild(src.firstChild.cloneNode(true));
+                    node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox"));
+                } else {
+                    node.setAttributeNS(this.xlinkns, "href", "#" + id);
+                }
                 node.setAttributeNS(null, "width", size);
                 node.setAttributeNS(null, "height", size);
                 node.setAttributeNS(null, "x", pos.x - offset);
@@ -317,10 +333,20 @@
                 node.setAttributeNS(null, "r", style.pointRadius);
             }
 
-            if (typeof style.rotation != "undefined" && pos) {
-                var rotation = OpenLayers.String.format(
-                    "rotate(${0} ${1} ${2})", [style.rotation, pos.x, pos.y]);
-                node.setAttributeNS(null, "transform", rotation);
+            var rotation = style.rotation;
+            if ((rotation !== undefined || node._rotation !== undefined) && pos) {
+                node._rotation = rotation;
+                rotation |= 0;
+                if(node.nodeName !== "svg") {
+                    node.setAttributeNS(null, "transform",
+                        "rotate(" + rotation + " " + pos.x + " " +
+                        pos.y + ")");
+                } else {
+                     var metrics = this.symbolMetrics[id];
+                     node.firstChild.setAttributeNS(null, "transform",
+                     "rotate(" + style.rotation + " " + metrics[1] +
+                         " " +  metrics[2] + ")");
+                }
             }
         }
         
@@ -335,12 +361,12 @@
             node.setAttributeNS(null, "stroke", style.strokeColor);
             node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity);
             node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor);
-            node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap);
+            node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round");
             // Hard-coded linejoin for now, to make it look the same as in VML.
             // There is no strokeLinejoin property yet for symbolizers.
             node.setAttributeNS(null, "stroke-linejoin", "round");
-            node.setAttributeNS(null, "stroke-dasharray", this.dashStyle(style,
-                widthFactor));
+            style.strokeDashstyle && node.setAttributeNS(null,
+                "stroke-dasharray", this.dashStyle(style, widthFactor));
         } else {
             node.setAttributeNS(null, "stroke", "none");
         }
@@ -348,7 +374,7 @@
         if (style.pointerEvents) {
             node.setAttributeNS(null, "pointer-events", style.pointerEvents);
         }
-		        
+                
         if (style.cursor != null) {
             node.setAttributeNS(null, "cursor", style.cursor);
         }
@@ -368,8 +394,8 @@
      */
     dashStyle: function(style, widthFactor) {
         var w = style.strokeWidth * widthFactor;
-
-        switch (style.strokeDashstyle) {
+        var str = style.strokeDashstyle;
+        switch (str) {
             case 'solid':
                 return 'none';
             case 'dot':
@@ -383,7 +409,7 @@
             case 'longdashdot':
                 return [8 * w, 4 * w, 1, 4 * w].join();
             default:
-                return style.strokeDashstyle.replace(/ /g, ",");
+                return OpenLayers.String.trim(str).replace(/\s+/g, ",");
         }
     },
     
@@ -673,11 +699,13 @@
 
         label.setAttributeNS(null, "x", x);
         label.setAttributeNS(null, "y", -y);
-        label.setAttributeNS(null, "pointer-events", "none");
         
         if (style.fontColor) {
             label.setAttributeNS(null, "fill", style.fontColor);
         }
+        if (style.fontOpacity) {
+            label.setAttributeNS(null, "opacity", style.fontOpacity);
+        }
         if (style.fontFamily) {
             label.setAttributeNS(null, "font-family", style.fontFamily);
         }
@@ -687,11 +715,20 @@
         if (style.fontWeight) {
             label.setAttributeNS(null, "font-weight", style.fontWeight);
         }
+        if(style.labelSelect === true) {
+            label.setAttributeNS(null, "pointer-events", "visible");
+            label._featureId = featureId;
+            tspan._featureId = featureId;
+            tspan._geometry = location;
+            tspan._geometryClass = location.CLASS_NAME;
+        } else {
+            label.setAttributeNS(null, "pointer-events", "none");
+        }
         var align = style.labelAlign || "cm";
         label.setAttributeNS(null, "text-anchor",
             OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]] || "middle");
 
-        if (this.isGecko) {
+        if (OpenLayers.IS_GECKO === true) {
             label.setAttributeNS(null, "dominant-baseline",
                 OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]] || "central");
         } else {
@@ -724,7 +761,7 @@
         var complete = true;
         var len = components.length;
         var strings = [];
-        var str, component, j;
+        var str, component;
         for(var i=0; i<len; i++) {
             component = components[i];
             renderCmp.push(component);
@@ -863,7 +900,6 @@
         var symbol = OpenLayers.Renderer.symbol[graphicName];
         if (!symbol) {
             throw new Error(graphicName + ' is not a valid symbol name');
-            return;
         }
 
         var symbolNode = this.nodeFactory(id, "symbol");
@@ -872,7 +908,7 @@
         var symbolExtent = new OpenLayers.Bounds(
                                     Number.MAX_VALUE, Number.MAX_VALUE, 0, 0);
 
-        var points = "";
+        var points = [];
         var x,y;
         for (var i=0; i<symbol.length; i=i+2) {
             x = symbol[i];
@@ -881,10 +917,10 @@
             symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
             symbolExtent.right = Math.max(symbolExtent.right, x);
             symbolExtent.top = Math.max(symbolExtent.top, y);
-            points += " " + x + "," + y;
+            points.push(x, ",", y);
         }
         
-        node.setAttributeNS(null, "points", points);
+        node.setAttributeNS(null, "points", points.join(" "));
         
         var width = symbolExtent.getWidth();
         var height = symbolExtent.getHeight();
@@ -893,11 +929,35 @@
         var viewBox = [symbolExtent.left - width,
                         symbolExtent.bottom - height, width * 3, height * 3];
         symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" "));
-        this.symbolSize[id] = Math.max(width, height) * 3;
+        this.symbolMetrics[id] = [
+            Math.max(width, height),
+            symbolExtent.getCenterLonLat().lon,
+            symbolExtent.getCenterLonLat().lat
+        ];
         
         this.defs.appendChild(symbolNode);
         return symbolNode.id;
     },
+    
+    /**
+     * Method: getFeatureIdFromEvent
+     * 
+     * Parameters:
+     * evt - {Object} An <OpenLayers.Event> object
+     *
+     * Returns:
+     * {<OpenLayers.Geometry>} A geometry from an event that 
+     *     happened on a layer.
+     */
+    getFeatureIdFromEvent: function(evt) {
+        var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments);
+        if(this.supportUse === false && !featureId) {
+            var target = evt.target;
+            featureId = target.parentNode && target != this.rendererRoot &&
+                target.parentNode._featureId;
+        }
+        return featureId;
+    },
 
     CLASS_NAME: "OpenLayers.Renderer.SVG"
 });

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Renderer/VML.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Renderer/VML.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Renderer/VML.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -11,7 +12,7 @@
  * Render vector features in browsers with VML capability.  Construct a new
  * VML renderer with the <OpenLayers.Renderer.VML> constructor.
  * 
- * Note that for all calculations in this class, we use toFixed() to round a 
+ * Note that for all calculations in this class, we use (num | 0) to truncate a 
  * float value to an integer. This is done because it seems that VML doesn't 
  * support float values.
  *
@@ -53,13 +54,16 @@
         if (!document.namespaces.olv) {
             document.namespaces.add("olv", this.xmlns);
             var style = document.createStyleSheet();
-            style.addRule('olv\\:*', "behavior: url(#default#VML); " +
-                                   "position: absolute; display: inline-block;");
+            var shapes = ['shape','rect', 'oval', 'fill', 'stroke', 'imagedata', 'group','textbox']; 
+            for (var i = 0, len = shapes.length; i < len; i++) {
+
+                style.addRule('olv\\:' + shapes[i], "behavior: url(#default#VML); " +
+                              "position: absolute; display: inline-block;");
+            }                  
         }
         
         OpenLayers.Renderer.Elements.prototype.initialize.apply(this, 
                                                                 arguments);
-        this.offset = {x: 0, y: 0};
     },
 
     /**
@@ -98,9 +102,9 @@
                                                                arguments);
         var resolution = this.getResolution();
     
-        var left = extent.left/resolution;
-        var top = extent.top/resolution - this.size.h;
-        if (resolutionChanged) {
+        var left = (extent.left/resolution) | 0;
+        var top = (extent.top/resolution - this.size.h) | 0;
+        if (resolutionChanged || !this.offset) {
             this.offset = {x: left, y: top};
             left = 0;
             top = 0;
@@ -111,14 +115,14 @@
 
         
         var org = left + " " + top;
-        this.root.setAttribute("coordorigin", org);
+        this.root.coordorigin = org;
         var roots = [this.root, this.vectorRoot, this.textRoot];
         var root;
         for(var i=0, len=roots.length; i<len; ++i) {
             root = roots[i];
 
             var size = this.size.w + " " + this.size.h;
-            root.setAttribute("coordsize", size);
+            root.coordsize = size;
             
         }
         // flip the VML display Y axis upside down so it 
@@ -211,11 +215,11 @@
     setStyle: function(node, style, options, geometry) {
         style = style  || node._style;
         options = options || node._options;
-        var widthFactor = 1;
-        
-        if (node._geometryClass == "OpenLayers.Geometry.Point") {
+        var fillColor = style.fillColor;
+
+        if (node._geometryClass === "OpenLayers.Geometry.Point") {
             if (style.externalGraphic) {
-        		if (style.graphicTitle) {
+                if (style.graphicTitle) {
                     node.title=style.graphicTitle;
                 } 
                 var width = style.graphicWidth || style.graphicHeight;
@@ -229,22 +233,21 @@
                 var yOffset = (style.graphicYOffset != undefined) ?
                     style.graphicYOffset : -(0.5 * height);
                 
-                node.style.left = ((geometry.x/resolution - this.offset.x)+xOffset).toFixed();
-                node.style.top = ((geometry.y/resolution - this.offset.y)-(yOffset+height)).toFixed();
+                node.style.left = (((geometry.x/resolution - this.offset.x)+xOffset) | 0) + "px";
+                node.style.top = (((geometry.y/resolution - this.offset.y)-(yOffset+height)) | 0) + "px";
                 node.style.width = width + "px";
                 node.style.height = height + "px";
                 node.style.flip = "y";
                 
-                // modify style/options for fill and stroke styling below
-                style.fillColor = "none";
+                // modify fillColor and options for stroke styling below
+                fillColor = "none";
                 options.isStroked = false;
             } else if (this.isComplexSymbol(style.graphicName)) {
                 var cache = this.importSymbol(style.graphicName);
-                node.setAttribute("path", cache.path);
-                node.setAttribute("coordorigin", cache.left + "," +
-                                                                cache.bottom);
+                node.path = cache.path;
+                node.coordorigin = cache.left + "," + cache.bottom;
                 var size = cache.size;
-                node.setAttribute("coordsize", size + "," + size);        
+                node.coordsize = size + "," + size;        
                 this.drawCircle(node, geometry, style.pointRadius);
                 node.style.flip = "y";
             } else {
@@ -254,9 +257,9 @@
 
         // fill 
         if (options.isFilled) { 
-            node.setAttribute("fillcolor", style.fillColor); 
+            node.fillcolor = fillColor; 
         } else { 
-            node.setAttribute("filled", "false"); 
+            node.filled = "false"; 
         }
         var fills = node.getElementsByTagName("fill");
         var fill = (fills.length == 0) ? null : fills[0];
@@ -268,18 +271,18 @@
             if (!fill) {
                 fill = this.createNode('olv:fill', node.id + "_fill");
             }
-            fill.setAttribute("opacity", style.fillOpacity);
+            fill.opacity = style.fillOpacity;
 
-            if (node._geometryClass == "OpenLayers.Geometry.Point" &&
+            if (node._geometryClass === "OpenLayers.Geometry.Point" &&
                     style.externalGraphic) {
 
                 // override fillOpacity
                 if (style.graphicOpacity) {
-                    fill.setAttribute("opacity", style.graphicOpacity);
+                    fill.opacity = style.graphicOpacity;
                 }
                 
-                fill.setAttribute("src", style.externalGraphic);
-                fill.setAttribute("type", "frame");
+                fill.src = style.externalGraphic;
+                fill.type = "frame";
                 
                 if (!(style.graphicWidth && style.graphicHeight)) {
                   fill.aspect = "atmost";
@@ -291,40 +294,43 @@
         }
 
         // additional rendering for rotated graphics or symbols
-        if (typeof style.rotation != "undefined") {
+        var rotation = style.rotation;
+        if ((rotation !== undefined || node._rotation !== undefined)) {
+            node._rotation = rotation;
             if (style.externalGraphic) {
-                this.graphicRotate(node, xOffset, yOffset);
+                this.graphicRotate(node, xOffset, yOffset, style);
                 // make the fill fully transparent, because we now have
                 // the graphic as imagedata element. We cannot just remove
                 // the fill, because this is part of the hack described
                 // in graphicRotate
-                fill.setAttribute("opacity", 0);
-            } else {
-                node.style.rotation = style.rotation;
+                fill.opacity = 0;
+            } else if(node._geometryClass === "OpenLayers.Geometry.Point") {
+                node.style.rotation = rotation || 0;
             }
         }
 
         // stroke 
-        if (options.isStroked) { 
-            node.setAttribute("strokecolor", style.strokeColor); 
-            node.setAttribute("strokeweight", style.strokeWidth + "px"); 
-        } else { 
-            node.setAttribute("stroked", "false"); 
-        }
         var strokes = node.getElementsByTagName("stroke");
         var stroke = (strokes.length == 0) ? null : strokes[0];
         if (!options.isStroked) {
+            node.stroked = false;
             if (stroke) {
-                node.removeChild(stroke);
+                stroke.on = false;
             }
         } else {
             if (!stroke) {
                 stroke = this.createNode('olv:stroke', node.id + "_stroke");
                 node.appendChild(stroke);
             }
-            stroke.setAttribute("opacity", style.strokeOpacity);
-            stroke.setAttribute("endcap", !style.strokeLinecap || style.strokeLinecap == 'butt' ? 'flat' : style.strokeLinecap);
-            stroke.setAttribute("dashstyle", this.dashStyle(style));
+            stroke.on = true;
+            stroke.color = style.strokeColor; 
+            stroke.weight = style.strokeWidth + "px"; 
+            stroke.opacity = style.strokeOpacity;
+            stroke.endcap = style.strokeLinecap == 'butt' ? 'flat' :
+                (style.strokeLinecap || 'round');
+            if (style.strokeDashstyle) {
+                stroke.dashstyle = this.dashStyle(style);
+            }
         }
         
         if (style.cursor != "inherit" && style.cursor != null) {
@@ -351,10 +357,11 @@
      * node    - {DOMElement}
      * xOffset - {Number} rotation center relative to image, x coordinate
      * yOffset - {Number} rotation center relative to image, y coordinate
+     * style   - {Object}
      */
-    graphicRotate: function(node, xOffset, yOffset) {
+    graphicRotate: function(node, xOffset, yOffset, style) {
         var style = style || node._style;
-        var options = node._options;
+        var rotation = style.rotation || 0;
         
         var aspectRatio, size;
         if (!(style.graphicWidth && style.graphicHeight)) {
@@ -370,7 +377,7 @@
                     xOffset = xOffset * aspectRatio;
                     style.graphicWidth = size * aspectRatio;
                     style.graphicHeight = size;
-                    this.graphicRotate(node, xOffset, yOffset);
+                    this.graphicRotate(node, xOffset, yOffset, style);
                 }
             }, this);
             img.src = style.externalGraphic;
@@ -408,9 +415,9 @@
             "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + 
             "src='', sizingMethod='scale')";
 
-        var rotation = style.rotation * Math.PI / 180;
-        var sintheta = Math.sin(rotation);
-        var costheta = Math.cos(rotation);
+        var rot = rotation * Math.PI / 180;
+        var sintheta = Math.sin(rot);
+        var costheta = Math.cos(rot);
 
         // do the rotation on the image
         var filter =
@@ -441,24 +448,28 @@
 
     /**
      * Method: postDraw
-     * Some versions of Internet Explorer seem to be unable to set fillcolor
-     * and strokecolor to "none" correctly before the fill node is appended to
-     * a visible vml node. This method takes care of that and sets fillcolor
-     * and strokecolor again if needed.
+     * Does some node postprocessing to work around browser issues:
+     * - Some versions of Internet Explorer seem to be unable to set fillcolor
+     *   and strokecolor to "none" correctly before the fill node is appended
+     *   to a visible vml node. This method takes care of that and sets
+     *   fillcolor and strokecolor again if needed.
+     * - In some cases, a node won't become visible after being drawn. Setting
+     *   style.visibility to "visible" works around that.
      * 
      * Parameters:
      * node - {DOMElement}
      */
     postDraw: function(node) {
+        node.style.visibility = "visible";
         var fillColor = node._style.fillColor;
         var strokeColor = node._style.strokeColor;
         if (fillColor == "none" &&
-                node.getAttribute("fillcolor") != fillColor) {
-            node.setAttribute("fillcolor", fillColor);
+                node.fillcolor != fillColor) {
+            node.fillcolor = fillColor;
         }
         if (strokeColor == "none" &&
-                node.getAttribute("strokecolor") != strokeColor) {
-            node.setAttribute("strokecolor", strokeColor);
+                node.strokecolor != strokeColor) {
+            node.strokecolor = strokeColor;
         }
     },
 
@@ -479,10 +490,10 @@
             var resolution = this.getResolution();
         
             var scaledBox = 
-                new OpenLayers.Bounds((bbox.left/resolution - this.offset.x).toFixed(),
-                                      (bbox.bottom/resolution - this.offset.y).toFixed(),
-                                      (bbox.right/resolution - this.offset.x).toFixed(),
-                                      (bbox.top/resolution - this.offset.y).toFixed());
+                new OpenLayers.Bounds((bbox.left/resolution - this.offset.x) | 0,
+                                      (bbox.bottom/resolution - this.offset.y) | 0,
+                                      (bbox.right/resolution - this.offset.x) | 0,
+                                      (bbox.top/resolution - this.offset.y) | 0);
             
             // Set the internal coordinate system to draw the path
             node.style.left = scaledBox.left + "px";
@@ -544,13 +555,13 @@
     createNode: function(type, id) {
         var node = document.createElement(type);
         if (id) {
-            node.setAttribute('id', id);
+            node.id = id;
         }
         
         // IE hack to make elements unselectable, to prevent 'blue flash'
         // while dragging vectors; #1410
-        node.setAttribute('unselectable', 'on', 0);
-        node.onselectstart = function() { return(false); };
+        node.unselectable = 'on';
+        node.onselectstart = OpenLayers.Function.False;
         
         return node;    
     },
@@ -648,8 +659,8 @@
         if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {
             var resolution = this.getResolution();
 
-            node.style.left = ((geometry.x /resolution - this.offset.x).toFixed() - radius) + "px";
-            node.style.top = ((geometry.y /resolution - this.offset.y).toFixed() - radius) + "px";
+            node.style.left = (((geometry.x /resolution - this.offset.x) | 0) - radius) + "px";
+            node.style.top = (((geometry.y /resolution - this.offset.y) | 0) - radius) + "px";
     
             var diameter = radius * 2;
             
@@ -714,9 +725,9 @@
         var comp, x, y;
         for (var i = 0; i < numComponents; i++) {
             comp = geometry.components[i];
-            x = (comp.x/resolution - this.offset.x);
-            y = (comp.y/resolution - this.offset.y);
-            parts[i] = " " + x.toFixed() + "," + y.toFixed() + " l ";
+            x = (comp.x/resolution - this.offset.x) | 0;
+            y = (comp.y/resolution - this.offset.y) | 0;
+            parts[i] = " " + x + "," + y + " l ";
         }
         var end = (closeLine) ? " x e" : " e";
         node.path = "m" + parts.join("") + end;
@@ -740,21 +751,43 @@
         var resolution = this.getResolution();
     
         var path = [];
-        var linearRing, i, j, len, ilen, comp, x, y;
-        for (j = 0, len=geometry.components.length; j<len; j++) {
-            linearRing = geometry.components[j];
-
+        var j, jj, points, area, first, second, i, ii, comp, pathComp, x, y;
+        for (j=0, jj=geometry.components.length; j<jj; j++) {
             path.push("m");
-            for (i=0, ilen=linearRing.components.length; i<ilen; i++) {
-                comp = linearRing.components[i];
-                x = comp.x / resolution - this.offset.x;
-                y = comp.y / resolution - this.offset.y;
-                path.push(" " + x.toFixed() + "," + y.toFixed());
+            points = geometry.components[j].components;
+            // we only close paths of interior rings with area
+            area = (j === 0);
+            first = null;
+            second = null;
+            for (i=0, ii=points.length; i<ii; i++) {
+                comp = points[i];
+                x = (comp.x / resolution - this.offset.x) | 0;
+                y = (comp.y / resolution - this.offset.y) | 0;
+                pathComp = " " + x + "," + y;
+                path.push(pathComp)
                 if (i==0) {
                     path.push(" l");
                 }
+                if (!area) {
+                    // IE improperly renders sub-paths that have no area.
+                    // Instead of checking the area of every ring, we confirm
+                    // the ring has at least three distinct points.  This does
+                    // not catch all non-zero area cases, but it greatly improves
+                    // interior ring digitizing and is a minor performance hit
+                    // when rendering rings with many points.
+                    if (!first) {
+                        first = pathComp;
+                    } else if (first != pathComp) {
+                        if (!second) {
+                            second = pathComp;
+                        } else if (second != pathComp) {
+                            // stop looking
+                            area = true;
+                        }
+                    }
+                }
             }
-            path.push(" x ");
+            path.push(area ? " x " : " ");
         }
         path.push("e");
         node.path = path.join("");
@@ -775,10 +808,10 @@
     drawRectangle: function(node, geometry) {
         var resolution = this.getResolution();
     
-        node.style.left = (geometry.x/resolution - this.offset.x) + "px";
-        node.style.top = (geometry.y/resolution - this.offset.y) + "px";
-        node.style.width = geometry.width/resolution + "px";
-        node.style.height = geometry.height/resolution + "px";
+        node.style.left = ((geometry.x/resolution - this.offset.x) | 0) + "px";
+        node.style.top = ((geometry.y/resolution - this.offset.y) | 0) + "px";
+        node.style.width = ((geometry.width/resolution) | 0) + "px";
+        node.style.height = ((geometry.height/resolution) | 0) + "px";
         
         return node;
     },
@@ -797,15 +830,18 @@
         var textbox = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_textbox", "olv:textbox");
         
         var resolution = this.getResolution();
-        label.style.left = (location.x/resolution - this.offset.x).toFixed() + "px";
-        label.style.top = (location.y/resolution - this.offset.y).toFixed() + "px";
+        label.style.left = ((location.x/resolution - this.offset.x) | 0) + "px";
+        label.style.top = ((location.y/resolution - this.offset.y) | 0) + "px";
         label.style.flip = "y";
 
         textbox.innerText = style.label;
 
-        if (style.fillColor) {
+        if (style.fontColor) {
             textbox.style.color = style.fontColor;
         }
+        if (style.fontOpacity) {
+            textbox.style.filter = 'alpha(opacity=' + (style.fontOpacity * 100) + ')';
+        }
         if (style.fontFamily) {
             textbox.style.fontFamily = style.fontFamily;
         }
@@ -815,8 +851,17 @@
         if (style.fontWeight) {
             textbox.style.fontWeight = style.fontWeight;
         }
+        if(style.labelSelect === true) {
+            label._featureId = featureId;
+            textbox._featureId = featureId;
+            textbox._geometry = location;
+            textbox._geometryClass = location.CLASS_NAME;
+        }
         textbox.style.whiteSpace = "nowrap";
-        textbox.inset = "0px,0px,0px,0px";
+        // fun with IE: IE7 in standards compliant mode does not display any
+        // text with a left inset of 0. So we set this to 1px and subtract one
+        // pixel later when we set label.style.left
+        textbox.inset = "1px,0px,0px,0px";
 
         if(!label.parentNode) {
             label.appendChild(textbox);
@@ -824,12 +869,16 @@
         }
 
         var align = style.labelAlign || "cm";
+        if (align.length == 1) {
+            align += "m";
+        }
         var xshift = textbox.clientWidth *
             (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);
         var yshift = textbox.clientHeight *
             (OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);
-        label.style.left = parseInt(label.style.left)-xshift+"px";
+        label.style.left = parseInt(label.style.left)-xshift-1+"px";
         label.style.top = parseInt(label.style.top)+yshift+"px";
+        
     },
 
     /**
@@ -852,8 +901,8 @@
         var comp, x, y;
         for (var i=0, len=geometry.components.length; i<len; i++) {
             comp = geometry.components[i];
-            x = comp.x / resolution - this.offset.x;
-            y = comp.y / resolution - this.offset.y;
+            x = (comp.x / resolution - this.offset.x) | 0;
+            y = (comp.y / resolution - this.offset.y) | 0;
             if ((i%3)==0 && (i/3)==0) {
                 path.push("m");
             } else if ((i%3)==1) {
@@ -912,7 +961,6 @@
         var symbol = OpenLayers.Renderer.symbol[graphicName];
         if (!symbol) {
             throw new Error(graphicName + ' is not a valid symbol name');
-            return;
         }
 
         var symbolExtent = new OpenLayers.Bounds(
@@ -920,8 +968,8 @@
         
         var pathitems = ["m"];
         for (var i=0; i<symbol.length; i=i+2) {
-            x = symbol[i];
-            y = symbol[i+1];
+            var x = symbol[i];
+            var y = symbol[i+1];
             symbolExtent.left = Math.min(symbolExtent.left, x);
             symbolExtent.bottom = Math.min(symbolExtent.bottom, y);
             symbolExtent.right = Math.max(symbolExtent.right, x);
@@ -941,8 +989,8 @@
             symbolExtent.bottom = symbolExtent.bottom - diff;
             symbolExtent.top = symbolExtent.top + diff;
         } else {
-            symbolExtent.left = symbolExtent.left - diff;
-            symbolExtent.right = symbolExtent.right + diff;
+            symbolExtent.left = symbolExtent.left + diff;
+            symbolExtent.right = symbolExtent.right - diff;
         }
         
         cache = {

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Renderer.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Renderer.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Renderer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -178,7 +179,14 @@
                 }
                 var rendered = this.drawGeometry(feature.geometry, style, feature.id);
                 if(style.display != "none" && style.label && rendered !== false) {
-                    this.drawText(feature.id, style, feature.geometry.getCentroid());
+                    var location = feature.geometry.getCentroid(); 
+                    if(style.labelXOffset || style.labelYOffset) {
+                        xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset;
+                        yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset;
+                        var res = this.getResolution();
+                        location.move(xOffset*res, yOffset*res);
+                    }
+                    this.drawText(feature.id, style, location);
                 } else {
                     this.removeText(feature.id);
                 }
@@ -258,8 +266,9 @@
             features = [features];
         }
         for(var i=0, len=features.length; i<len; ++i) {
-            this.eraseGeometry(features[i].geometry);
-            this.removeText(features[i].id);
+            var feature = features[i];
+            this.eraseGeometry(feature.geometry, feature.id);
+            this.removeText(feature.id);
         }
     },
     
@@ -270,8 +279,9 @@
      * 
      * Parameters:
      * geometry - {<OpenLayers.Geometry>} 
+     * featureId - {String}
      */
-    eraseGeometry: function(geometry) {},
+    eraseGeometry: function(geometry, featureId) {},
     
     /**
      * Method: moveRoot
@@ -296,6 +306,57 @@
     getRenderLayerId: function() {
         return this.container.id;
     },
+    
+    /**
+     * Method: applyDefaultSymbolizer
+     * 
+     * Parameters:
+     * symbolizer - {Object}
+     * 
+     * Returns:
+     * {Object}
+     */
+    applyDefaultSymbolizer: function(symbolizer) {
+        var result = OpenLayers.Util.extend({},
+            OpenLayers.Renderer.defaultSymbolizer);
+        if(symbolizer.stroke === false) {
+            delete result.strokeWidth;
+            delete result.strokeColor;
+        }
+        if(symbolizer.fill === false) {
+            delete result.fillColor;
+        }
+        OpenLayers.Util.extend(result, symbolizer);
+        return result;
+    },
 
     CLASS_NAME: "OpenLayers.Renderer"
-});
\ No newline at end of file
+});
+
+/**
+ * Constant: OpenLayers.Renderer.defaultSymbolizer
+ * {Object} Properties from this symbolizer will be applied to symbolizers
+ *     with missing properties. This can also be used to set a global
+ *     symbolizer default in OpenLayers. To be SLD 1.x compliant, add the
+ *     following code before rendering any vector features:
+ * (code)
+ * OpenLayers.Renderer.defaultSymbolizer = {
+ *     fillColor: "#808080",
+ *     fillOpacity: 1,
+ *     strokeColor: "#000000",
+ *     strokeOpacity: 1,
+ *     strokeWidth: 1,
+ *     pointRadius: 3,
+ *     graphicName: "square"
+ * };
+ * (end)
+ */
+OpenLayers.Renderer.defaultSymbolizer = {
+    fillColor: "#000000",
+    strokeColor: "#000000",
+    strokeWidth: 2,
+    fillOpacity: 1,
+    strokeOpacity: 1,
+    pointRadius: 0
+};
+    

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Request/XMLHttpRequest.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Request/XMLHttpRequest.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Request/XMLHttpRequest.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,4 +1,4 @@
-// Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -23,11 +23,13 @@
 
     // Define on browser type
     var bGecko    = !!window.controllers,
-        bIE        = window.document.all && !window.opera;
+        bIE        = window.document.all && !window.opera,
+        bIE7    = bIE && window.navigator.userAgent.match(/MSIE ([\.0-9]+)/) && RegExp.$1 == 7;
 
     // Constructor
     function cXMLHttpRequest() {
-        this._object    = oXMLHttpRequest ? new oXMLHttpRequest : new window.ActiveXObject('Microsoft.XMLHTTP');
+        this._object    = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
+        this._listeners    = [];
     };
 
     // BUGFIX: Firefox with Firebug installed would break pages if not executed
@@ -43,10 +45,10 @@
 
     // Public Properties
     cXMLHttpRequest.prototype.readyState    = cXMLHttpRequest.UNSENT;
-    cXMLHttpRequest.prototype.responseText    = "";
+    cXMLHttpRequest.prototype.responseText    = '';
     cXMLHttpRequest.prototype.responseXML    = null;
     cXMLHttpRequest.prototype.status        = 0;
-    cXMLHttpRequest.prototype.statusText    = "";
+    cXMLHttpRequest.prototype.statusText    = '';
 
     // Instance-level Events Handlers
     cXMLHttpRequest.prototype.onreadystatechange    = null;
@@ -59,24 +61,50 @@
 
     // Public Methods
     cXMLHttpRequest.prototype.open    = function(sMethod, sUrl, bAsync, sUser, sPassword) {
+        // Delete headers, required when object is reused
+        delete this._headers;
 
+        // When bAsync parameter value is omitted, use true as default
+        if (arguments.length < 3)
+            bAsync    = true;
+
         // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
         this._async        = bAsync;
 
         // Set the onreadystatechange handler
         var oRequest    = this,
-            nState        = this.readyState;
+            nState        = this.readyState,
+            fOnUnload;
 
         // BUGFIX: IE - memory leak on page unload (inter-page leak)
-        if (bIE) {
-            var fOnUnload    = function() {
-                if (oRequest._object.readyState != cXMLHttpRequest.DONE)
+        if (bIE && bAsync) {
+            fOnUnload = function() {
+                if (nState != cXMLHttpRequest.DONE) {
                     fCleanTransport(oRequest);
+                    // Safe to abort here since onreadystatechange handler removed
+                    oRequest.abort();
+                }
             };
-            if (bAsync)
                 window.attachEvent("onunload", fOnUnload);
         }
 
+        // Add method sniffer
+        if (cXMLHttpRequest.onopen)
+            cXMLHttpRequest.onopen.apply(this, arguments);
+
+        if (arguments.length > 4)
+            this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+        else
+        if (arguments.length > 3)
+            this._object.open(sMethod, sUrl, bAsync, sUser);
+        else
+            this._object.open(sMethod, sUrl, bAsync);
+
+        if (!bGecko && !bIE) {
+            this.readyState    = cXMLHttpRequest.OPENED;
+            fReadyStateChange(this);
+        }
+
         this._object.onreadystatechange    = function() {
             if (bGecko && !bAsync)
                 return;
@@ -87,7 +115,7 @@
             //
             fSynchronizeValues(oRequest);
 
-            // BUGFIX: Firefox fires unneccesary DONE when aborting
+            // BUGFIX: Firefox fires unnecessary DONE when aborting
             if (oRequest._aborted) {
                 // Reset readyState to UNSENT
                 oRequest.readyState    = cXMLHttpRequest.UNSENT;
@@ -110,7 +138,14 @@
                     cXMLHttpRequest.call(oRequest);
 
                     // Re-send request
+                    if (sUser) {
+                         if (sPassword)
                     oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+                        else
+                            oRequest._object.open(sMethod, sUrl, bAsync, sUser);
+                    }
+                    else
+                        oRequest._object.open(sMethod, sUrl, bAsync);
                     oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
                     // Copy headers set
                     if (oRequest._headers)
@@ -154,7 +189,7 @@
                     };
                     oRequest._object.send(null);
 
-                    // Return now - wait untill re-sent request is finished
+                    // Return now - wait until re-sent request is finished
                     return;
                 };
 */
@@ -168,19 +203,6 @@
                 fReadyStateChange(oRequest);
 
             nState    = oRequest.readyState;
-        };
-
-        // Add method sniffer
-        if (cXMLHttpRequest.onopen)
-            cXMLHttpRequest.onopen.apply(this, arguments);
-
-        this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
-
-        // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
-        if (!bAsync && bGecko) {
-            this.readyState    = cXMLHttpRequest.OPENED;
-
-            fReadyStateChange(this);
         }
     };
     cXMLHttpRequest.prototype.send    = function(vData) {
@@ -221,7 +243,7 @@
         if (cXMLHttpRequest.onabort)
             cXMLHttpRequest.onabort.apply(this, arguments);
 
-        // BUGFIX: Gecko - unneccesary DONE when aborting
+        // BUGFIX: Gecko - unnecessary DONE when aborting
         if (this.readyState > cXMLHttpRequest.UNSENT)
             this._aborted    = true;
 
@@ -244,34 +266,86 @@
 
         return this._object.setRequestHeader(sName, sValue);
     };
+
+    // EventTarget interface implementation
+    cXMLHttpRequest.prototype.addEventListener    = function(sName, fHandler, bUseCapture) {
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
+                return;
+        // Add listener
+        this._listeners.push([sName, fHandler, bUseCapture]);
+    };
+
+    cXMLHttpRequest.prototype.removeEventListener    = function(sName, fHandler, bUseCapture) {
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
+                break;
+        // Remove listener
+        if (oListener)
+            this._listeners.splice(nIndex, 1);
+    };
+
+    cXMLHttpRequest.prototype.dispatchEvent    = function(oEvent) {
+        var oEventPseudo    = {
+            'type':            oEvent.type,
+            'target':        this,
+            'currentTarget':this,
+            'eventPhase':    2,
+            'bubbles':        oEvent.bubbles,
+            'cancelable':    oEvent.cancelable,
+            'timeStamp':    oEvent.timeStamp,
+            'stopPropagation':    function() {},    // There is no flow
+            'preventDefault':    function() {},    // There is no default action
+            'initEvent':        function() {}    // Original event object should be initialized
+        };
+
+        // Execute onreadystatechange
+        if (oEventPseudo.type == "readystatechange" && this.onreadystatechange)
+            (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
+
+        // Execute listeners
+        for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
+            if (oListener[0] == oEventPseudo.type && !oListener[2])
+                (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
+    };
+
+    //
     cXMLHttpRequest.prototype.toString    = function() {
         return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
     };
+
     cXMLHttpRequest.toString    = function() {
         return '[' + "XMLHttpRequest" + ']';
     };
 
     // Helper function
     function fReadyStateChange(oRequest) {
-        // Execute onreadystatechange
-        if (oRequest.onreadystatechange)
-            oRequest.onreadystatechange.apply(oRequest);
-
         // Sniffing code
         if (cXMLHttpRequest.onreadystatechange)
             cXMLHttpRequest.onreadystatechange.apply(oRequest);
+
+        // Fake event
+        oRequest.dispatchEvent({
+            'type':            "readystatechange",
+            'bubbles':        false,
+            'cancelable':    false,
+            'timeStamp':    new Date + 0
+        });
     };
 
     function fGetDocument(oRequest) {
-        var oDocument    = oRequest.responseXML;
+        var oDocument    = oRequest.responseXML,
+            sResponse    = oRequest.responseText;
         // Try parsing responseText
-        if (bIE && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
-            oDocument    = new ActiveXObject('Microsoft.XMLDOM');
-            oDocument.loadXML(oRequest.responseText);
+        if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
+            oDocument    = new window.ActiveXObject("Microsoft.XMLDOM");
+            oDocument.async                = false;
+            oDocument.validateOnParse    = false;
+            oDocument.loadXML(sResponse);
         }
         // Check if there is no error in document
         if (oDocument)
-            if ((bIE && oDocument.parseError != 0) || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
+            if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
                 return null;
         return oDocument;
     };
@@ -286,9 +360,6 @@
     function fCleanTransport(oRequest) {
         // BUGFIX: IE - memory leak (on-page leak)
         oRequest._object.onreadystatechange    = new window.Function;
-
-        // Delete private properties
-        delete oRequest._headers;
     };
 
     // Internet Explorer 5.0 (missing apply)

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Request.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Request.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Request.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -128,7 +129,11 @@
             }
         }
         if(config.proxy && (url.indexOf("http") == 0)) {
-            url = config.proxy + encodeURIComponent(url);
+            if(typeof config.proxy == "function") {
+                url = config.proxy(url);
+            } else {
+                url = config.proxy + encodeURIComponent(url);
+            }
         }
         request.open(
             config.method, url, config.async, config.user, config.password
@@ -137,29 +142,12 @@
             request.setRequestHeader(header, config.headers[header]);
         }
 
-        // bind callbacks to readyState 4 (done)
-        var complete = (config.scope) ?
-            OpenLayers.Function.bind(config.callback, config.scope) :
-            config.callback;
-        
-        // optional success callback
-        var success;
-        if(config.success) {
-            success = (config.scope) ?
-                OpenLayers.Function.bind(config.success, config.scope) :
-                config.success;
-        }
+        var events = this.events;
 
-        // optional failure callback
-        var failure;
-        if(config.failure) {
-            failure = (config.scope) ?
-                OpenLayers.Function.bind(config.failure, config.scope) :
-                config.failure;
-        }
+        // we want to execute runCallbacks with "this" as the
+        // execution scope
+        var self = this;
         
-        var events = this.events;
-         
         request.onreadystatechange = function() {
             if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
                 var proceed = events.triggerEvent(
@@ -167,25 +155,9 @@
                     {request: request, config: config, requestUrl: url}
                 );
                 if(proceed !== false) {
-                    complete(request);
-                    if (!request.status || (request.status >= 200 && request.status < 300)) {
-                        events.triggerEvent(
-                            "success",
-                            {request: request, config: config, requestUrl: url}
-                        );
-                        if(success) {
-                            success(request);
-                        }
-                    }
-                    if(request.status && (request.status < 200 || request.status >= 300)) {                    
-                        events.triggerEvent(
-                            "failure",
-                            {request: request, config: config, requestUrl: url}
-                        );
-                        if(failure) {
-                            failure(request);
-                        }
-                    }
+                    self.runCallbacks(
+                        {request: request, config: config, requestUrl: url}
+                    );
                 }
             }
         };
@@ -197,13 +169,67 @@
             request.send(config.data);
         } else {
             window.setTimeout(function(){
-                request.send(config.data);
+                if (request._aborted !== true) {
+                    request.send(config.data);
+                }
             }, 0);
         }
         return request;
     },
     
     /**
+     * Method: runCallbacks
+     * Calls the complete, success and failure callbacks. Application
+     *    can listen to the "complete" event, have the listener 
+     *    display a confirm window and always return false, and
+     *    execute OpenLayers.Request.runCallbacks if the user
+     *    hits "yes" in the confirm window.
+     *
+     * Parameters:
+     * options - {Object} Hash containing request, config and requestUrl keys
+     */
+    runCallbacks: function(options) {
+        var request = options.request;
+        var config = options.config;
+        
+        // bind callbacks to readyState 4 (done)
+        var complete = (config.scope) ?
+            OpenLayers.Function.bind(config.callback, config.scope) :
+            config.callback;
+        
+        // optional success callback
+        var success;
+        if(config.success) {
+            success = (config.scope) ?
+                OpenLayers.Function.bind(config.success, config.scope) :
+                config.success;
+        }
+
+        // optional failure callback
+        var failure;
+        if(config.failure) {
+            failure = (config.scope) ?
+                OpenLayers.Function.bind(config.failure, config.scope) :
+                config.failure;
+        }
+
+        complete(request);
+
+        if (!request.status || (request.status >= 200 && request.status < 300)) {
+            this.events.triggerEvent("success", options);
+            if(success) {
+                success(request);
+            }
+        }
+        if(request.status && (request.status < 200 || request.status >= 300)) {                    
+            this.events.triggerEvent("failure", options);
+            if(failure) {
+                failure(request);
+            }
+        }
+    },
+    
+    /**
      * APIMethod: GET
      * Send an HTTP GET request.  Additional configuration properties are
      *     documented in the <issue> method, with the method property set

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Rule.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Rule.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Rule.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,11 +1,17 @@
-/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
- * for the full text of the license. */
+/* 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/Util.js
  * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Symbolizer/Point.js
+ * @requires OpenLayers/Symbolizer/Line.js
+ * @requires OpenLayers/Symbolizer/Polygon.js
+ * @requires OpenLayers/Symbolizer/Text.js
+ * @requires OpenLayers/Symbolizer/Raster.js
  */
 
 /**
@@ -24,7 +30,7 @@
      * APIProperty: name
      * {String} name of this rule
      */
-    name: 'default',
+    name: null,
     
     /**
      * Property: title
@@ -74,6 +80,17 @@
     symbolizer: null,
     
     /**
+     * Property: symbolizers
+     * {Array} Collection of symbolizers associated with this rule.  If 
+     *     provided at construction, the symbolizers array has precedence
+     *     over the deprecated symbolizer property.  Note that multiple 
+     *     symbolizers are not currently supported by the vector renderers.
+     *     Rules with multiple symbolizers are currently only useful for
+     *     maintaining elements in an SLD document.
+     */
+    symbolizers: null,
+    
+    /**
      * APIProperty: minScaleDenominator
      * {Number} or {String} minimum scale at which to draw the feature.
      * In the case of a String, this can be a combination of text and
@@ -103,6 +120,9 @@
     initialize: function(options) {
         this.symbolizer = {};
         OpenLayers.Util.extend(this, options);
+        if (this.symbolizers) {
+            delete this.symbolizer;
+        }
         this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
     },
 
@@ -115,6 +135,7 @@
             this.symbolizer[i] = null;
         }
         this.symbolizer = null;
+        delete this.symbolizers;
     },
     
     /**
@@ -187,16 +208,26 @@
      */
     clone: function() {
         var options = OpenLayers.Util.extend({}, this);
-        // clone symbolizer
-        options.symbolizer = {};
-        for(var key in this.symbolizer) {
-            value = this.symbolizer[key];
-            type = typeof value;
-            if(type === "object") {
-                options.symbolizer[key] = OpenLayers.Util.extend({}, value);
-            } else if(type === "string") {
-                options.symbolizer[key] = value;
+        if (this.symbolizers) {
+            // clone symbolizers
+            var len = this.symbolizers.length;
+            options.symbolizers = new Array(len);
+            for (var i=0; i<len; ++i) {
+                options.symbolizers[i] = this.symbolizers[i].clone();
             }
+        } else {
+            // clone symbolizer
+            options.symbolizer = {};
+            var value, type;
+            for(var key in this.symbolizer) {
+                value = this.symbolizer[key];
+                type = typeof value;
+                if(type === "object") {
+                    options.symbolizer[key] = OpenLayers.Util.extend({}, value);
+                } else if(type === "string") {
+                    options.symbolizer[key] = value;
+                }
+            }
         }
         // clone filter
         options.filter = this.filter && this.filter.clone();

Modified: sandbox/ahocevar/playground/lib/OpenLayers/SingleFile.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/SingleFile.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/SingleFile.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,9 +1,43 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 var OpenLayers = {
-    singleFile: true
-};
+    /**
+     * Constant: VERSION_NUMBER
+     */
+    VERSION_NUMBER: "$Revision$",
 
+    /**
+     * Constant: singleFile
+     * TODO: remove this in 3.0 when we stop supporting build profiles that
+     * include OpenLayers.js
+     */
+    singleFile: true,
 
+    /**
+     * Method: _getScriptLocation
+     * Return the path to this script. This is also implemented in
+     * OpenLayers.js
+     *
+     * Returns:
+     * {String} Path to this script
+     */
+    _getScriptLocation: (function() {
+        var r = new RegExp("(^|(.*?\\/))(OpenLayers\.js)(\\?|$)"),
+            s = document.getElementsByTagName('script'),
+            src, m, l = "";
+        for(var i=0, len=s.length; i<len; i++) {
+            src = s[i].getAttribute('src');
+            if(src) {
+                var m = src.match(r);
+                if(m) {
+                    l = m[1];
+                    break;
+                }
+            }
+        }
+        return (function() { return l; });
+    })()
+};


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/SingleFile.js
___________________________________________________________________
Added: svn:keywords
   + Revision


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Strategy
___________________________________________________________________
Modified: svn:mergeinfo
   - 
   + /trunk/openlayers/lib/OpenLayers/Strategy:7565-7706,7733-10919

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Filter.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Strategy/Filter.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Filter.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Filter.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,160 @@
+/* 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/Strategy.js
+ * @requires OpenLayers/Filter.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Filter
+ * Strategy for limiting features that get added to a layer by 
+ *     evaluating a filter.  The strategy maintains a cache of
+ *     all features until removeFeatures is called on the layer.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Filter = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * APIProperty: filter
+     * {<OpenLayers.Filter>}  Filter for limiting features sent to the layer.
+     *     Use the <setFilter> method to update this filter after construction.
+     */
+    filter: null,
+    
+    /**
+     * Property: cache
+     * {Array(<OpenLayers.Feature.Vector>)} List of currently cached
+     *     features.
+     */
+    cache: null,
+    
+    /**
+     * Property: caching
+     * {Boolean} The filter is currently caching features.
+     */
+    caching: false,
+    
+    /**
+     * Constructor: OpenLayers.Strategy.Filter
+     * Create a new filter strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Strategy.prototype.initialize.apply(this, [options]);
+    },
+
+    /**
+     * APIMethod: activate
+     * Activate the strategy.  Register any listeners, do appropriate setup.
+     *     By default, this strategy automatically activates itself when a layer
+     *     is added to a map.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated or false if
+     *      the strategy was already active.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.apply(this, arguments);
+        if (activated) {
+            this.cache = [];
+            this.layer.events.on({
+                "beforefeaturesadded": this.handleAdd,
+                "beforefeaturesremoved": this.handleRemove,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy.  Clear the feature cache.
+     *
+     * Returns:
+     * {Boolean} True if the strategy was successfully deactivated or false if
+     *      the strategy was already inactive.
+     */
+    deactivate: function() {
+        this.cache = null;
+        if (this.layer && this.layer.events) {
+            this.layer.events.un({
+                "beforefeaturesadded": this.handleAdd,
+                "beforefeaturesremoved": this.handleRemove,
+                scope: this
+            });            
+        }
+        return OpenLayers.Strategy.prototype.deactivate.apply(this, arguments);
+    },
+    
+    /**
+     * Method: handleAdd
+     */
+    handleAdd: function(event) {
+        if (!this.caching && this.filter) {
+            var features = event.features;
+            event.features = [];
+            var feature;
+            for (var i=0, ii=features.length; i<ii; ++i) {
+                feature = features[i];
+                if (this.filter.evaluate(feature)) {
+                    event.features.push(feature);
+                } else {
+                    this.cache.push(feature);
+                }
+            }
+        }
+    },
+    
+    /**
+     * Method: handleRemove
+     */
+    handleRemove: function(event) {
+        if (!this.caching) {
+            this.cache = [];
+        }
+    },
+
+    /** 
+     * APIMethod: setFilter
+     * Update the filter for this strategy.  This will re-evaluate
+     *     any features on the layer and in the cache.  Only features
+     *     for which filter.evalute(feature) returns true will be
+     *     added to the layer.  Others will be cached by the strategy.
+     *
+     * Parameters:
+     * filter - <OpenLayers.Filter> A filter for evaluating features.
+     */
+    setFilter: function(filter) {
+        this.filter = filter;
+        var previousCache = this.cache;
+        this.cache = [];
+        // look through layer for features to remove from layer
+        this.handleAdd({features: this.layer.features});
+        // cache now contains features to remove from layer
+        if (this.cache.length > 0) {
+            this.caching = true;
+            this.layer.removeFeatures(this.cache.slice(), {silent: true});
+            this.caching = false;
+        }
+        // now look through previous cache for features to add to layer
+        if (previousCache.length > 0) {
+            var event = {features: previousCache};
+            this.handleAdd(event);
+            // event has features to add to layer
+            this.caching = true;
+            this.layer.addFeatures(event.features, {silent: true});
+            this.caching = false;
+        }
+    },
+
+    CLASS_NAME: "OpenLayers.Strategy.Filter"
+
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Fixed.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Fixed.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Fixed.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -19,7 +20,7 @@
      * APIProperty: preload
      * {Boolean} Load data before layer made visible. Enabling this may result
      *   in considerable overhead if your application loads many data layers
-     *   that are not visible by default. Default is true.
+     *   that are not visible by default. Default is false.
      */
     preload: false,
 
@@ -97,12 +98,14 @@
      * options - {Object} options to pass to protocol read.
      */
     load: function(options) {
-        this.layer.events.triggerEvent("loadstart");
-        this.layer.protocol.read(OpenLayers.Util.applyDefaults({
-            callback: this.merge,
-            scope: this
+        var layer = this.layer;
+        layer.events.triggerEvent("loadstart");
+        layer.protocol.read(OpenLayers.Util.applyDefaults({
+            callback: OpenLayers.Function.bind(this.merge, this,
+                layer.map.getProjectionObject()),
+            filter: layer.filter
         }, options));
-        this.layer.events.un({
+        layer.events.un({
             "visibilitychanged": this.load,
             scope: this
         });
@@ -111,25 +114,28 @@
     /**
      * Method: merge
      * Add all features to the layer.
+     *
+     * Parameters:
+     * mapProjection - {OpenLayers.Projection} the map projection
+     * resp - {Object} options to pass to protocol read.
      */
-    merge: function(resp) {
-        this.layer.destroyFeatures();
+    merge: function(mapProjection, resp) {
+        var layer = this.layer;
+        layer.destroyFeatures();
         var features = resp.features;
         if (features && features.length > 0) {
-            var remote = this.layer.projection;
-            var local = this.layer.map.getProjectionObject();
-            if(!local.equals(remote)) {
+            if(!mapProjection.equals(layer.projection)) {
                 var geom;
                 for(var i=0, len=features.length; i<len; ++i) {
                     geom = features[i].geometry;
                     if(geom) {
-                        geom.transform(remote, local);
+                        geom.transform(layer.projection, mapProjection);
                     }
                 }
             }
-            this.layer.addFeatures(features);
+            layer.addFeatures(features);
         }
-        this.layer.events.triggerEvent("loadend");
+        layer.events.triggerEvent("loadend");
     },
 
     CLASS_NAME: "OpenLayers.Strategy.Fixed"

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Refresh.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Strategy/Refresh.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Refresh.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Strategy/Refresh.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,140 @@
+/* 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/Strategy.js
+ */
+
+/**
+ * Class: OpenLayers.Strategy.Refresh
+ * A strategy that refreshes the layer. By default the strategy waits for a
+ *     call to <refresh> before refreshing.  By configuring the strategy with 
+ *     the <interval> option, refreshing can take place automatically.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Strategy>
+ */
+OpenLayers.Strategy.Refresh = OpenLayers.Class(OpenLayers.Strategy, {
+    
+    /**
+     * Property: force
+     * {Boolean} Force a refresh on the layer. Default is false.
+     */
+    force: false,
+
+    /**
+     * Property: interval
+     * {Number} Auto-refresh. Default is 0.  If > 0, layer will be refreshed 
+     *     every N milliseconds.
+     */
+    interval: 0,
+    
+    /**
+     * Property: timer
+     * {Number} The id of the timer.
+     */
+    timer: null,
+
+    /**
+     * Constructor: OpenLayers.Strategy.Refresh
+     * Create a new Refresh strategy.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     instance.
+     */
+    initialize: function(options) {
+        OpenLayers.Strategy.prototype.initialize.apply(this, [options]);
+    },
+   
+    /**
+     * APIMethod: activate
+     * Activate the strategy. Register any listeners, do appropriate setup.
+     * 
+     * Returns:
+     * {Boolean} True if the strategy was successfully activated.
+     */
+    activate: function() {
+        var activated = OpenLayers.Strategy.prototype.activate.call(this);
+        if(activated) {
+            if(this.layer.visibility === true) {
+                this.start();
+            } 
+            this.layer.events.on({
+                "visibilitychanged": this.reset,
+                scope: this
+            });
+        }
+        return activated;
+    },
+    
+    /**
+     * APIMethod: deactivate
+     * Deactivate the strategy. Unregister any listeners, do appropriate
+     *     tear-down.
+     * 
+     * Returns:
+     * {Boolean} True if the strategy was successfully deactivated.
+     */
+    deactivate: function() {
+        var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+        if(deactivated) {
+            this.stop();
+        }
+        return deactivated;
+    },
+    
+    /**
+     * Method: reset
+     * Start or cancel the refresh interval depending on the visibility of 
+     *     the layer.
+     */
+    reset: function() {
+        if(this.layer.visibility === true) {
+            this.start();
+        } else {
+            this.stop();
+        }
+    },
+    
+    /**
+     * Method: start
+     * Start the refresh interval. 
+     */
+    start: function() {
+        if(this.interval && typeof this.interval === "number" && 
+            this.interval > 0) {
+
+            this.timer = window.setInterval(
+                OpenLayers.Function.bind(this.refresh, this),
+                this.interval);
+        }
+    },
+    
+    /**
+     * APIMethod: refresh
+     * Tell the strategy to refresh which will refresh the layer.
+     */
+    refresh: function() {
+        if (this.layer && this.layer.refresh && 
+            typeof this.layer.refresh == "function") {
+
+            this.layer.refresh({force: this.force});
+        }
+    },
+   
+    /**
+     * Method: stop
+     * Cancels the refresh interval. 
+     */
+    stop: function() {
+        if(this.timer !== null) {
+            window.clearInterval(this.timer);
+            this.timer = null;
+        }
+    },
+    
+    CLASS_NAME: "OpenLayers.Strategy.Refresh" 
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Strategy.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Strategy.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Strategy.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**


Property changes on: sandbox/ahocevar/playground/lib/OpenLayers/Strategy.js
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Style.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Style.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Style.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
-/* 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. */
+/* 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. */
 
 
 /**
@@ -16,6 +17,12 @@
 OpenLayers.Style = OpenLayers.Class({
 
     /**
+     * Property: id
+     * {String} A unique id for this session.
+     */
+    id: null,
+    
+    /**
      * APIProperty: name
      * {String}
      */
@@ -119,6 +126,7 @@
         this.setDefaultStyle(style ||
                              OpenLayers.Feature.Vector.style["default"]);
 
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
     },
 
     /** 
@@ -207,7 +215,7 @@
             var defaults = this.defaultStyle;
             OpenLayers.Util.applyDefaults(symbolizer, {
                 pointRadius: defaults.pointRadius
-            })
+            });
             if(symbolizer.stroke === true || symbolizer.graphic === true) {
                 OpenLayers.Util.applyDefaults(symbolizer, {
                     strokeWidth: defaults.strokeWidth,
@@ -256,10 +264,11 @@
      * {Object} the modified style
      */
     createLiterals: function(style, feature) {
-        var context = this.context || feature.attributes || feature.data;
+        var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);
+        OpenLayers.Util.extend(context, this.context);
         
         for (var i in this.propertyStyles) {
-            style[i] = OpenLayers.Style.createLiteral(style[i], context, feature);
+            style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i);
         }
         return style;
     },
@@ -332,7 +341,7 @@
      * rules - {Array(<OpenLayers.Rule>)}
      */
     addRules: function(rules) {
-        this.rules = this.rules.concat(rules);
+        Array.prototype.push.apply(this.rules, rules);
         this.propertyStyles = this.findPropertyStyles();
     },
     
@@ -368,6 +377,29 @@
         }
     },
     
+    /**
+     * APIMethod: clone
+     * Clones this style.
+     * 
+     * Returns:
+     * {<OpenLayers.Style>} Clone of this style.
+     */
+    clone: function() {
+        var options = OpenLayers.Util.extend({}, this);
+        // clone rules
+        if(this.rules) {
+            options.rules = [];
+            for(var i=0, len=this.rules.length; i<len; ++i) {
+                options.rules.push(this.rules[i].clone());
+            }
+        }
+        // clone context
+        options.context = this.context && OpenLayers.Util.extend({}, this.context);
+        //clone default style
+        var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle);
+        return new OpenLayers.Style(defaultStyle, options);
+    },
+    
     CLASS_NAME: "OpenLayers.Style"
 });
 
@@ -383,17 +415,20 @@
  *         will be replaced by the value of the "bar" attribute of the passed
  *         feature.
  * context - {Object} context to take attribute values from
- * feature - {OpenLayers.Feature.Vector} The feature that will be passed
- *     to <OpenLayers.String.format> for evaluating functions in the context.
+ * feature - {<OpenLayers.Feature.Vector>} optional feature to pass to
+ *           <OpenLayers.String.format> for evaluating functions in the
+ *           context.
+ * property - {String} optional, name of the property for which the literal is
+ *            being created for evaluating functions in the context.
  * 
  * Returns:
  * {String} the parsed value. In the example of the value parameter above, the
  * result would be "foo valueOfBar", assuming that the passed feature has an
  * attribute named "bar" with the value "valueOfBar".
  */
-OpenLayers.Style.createLiteral = function(value, context, feature) {
+OpenLayers.Style.createLiteral = function(value, context, feature, property) {
     if (typeof value == "string" && value.indexOf("${") != -1) {
-        value = OpenLayers.String.format(value, context, [feature]);
+        value = OpenLayers.String.format(value, context, [feature, property]);
         value = (isNaN(value) || !value) ? value : parseFloat(value);
     }
     return value;
@@ -404,4 +439,5 @@
  * {Array} prefixes of the sld symbolizers. These are the
  * same as the main geometry types
  */
-OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text'];
+OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text',
+    'Raster'];

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Style2.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Style2.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Style2.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Style2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,111 @@
+/* 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/Rule.js
+ * @requires OpenLayers/Symbolizer/Point.js
+ * @requires OpenLayers/Symbolizer/Line.js
+ * @requires OpenLayers/Symbolizer/Polygon.js
+ * @requires OpenLayers/Symbolizer/Text.js
+ * @requires OpenLayers/Symbolizer/Raster.js
+ */
+
+/**
+ * Class: OpenLayers.Style2
+ * This class represents a collection of rules for rendering features.
+ */
+OpenLayers.Style2 = OpenLayers.Class({
+
+    /**
+     * Property: id
+     * {String} A unique id for this session.
+     */
+    id: null,
+    
+    /**
+     * APIProperty: name
+     * {String} Style identifier.
+     */
+    name: null,
+    
+    /**
+     * APIProperty: title
+     * {String} Title of this style.
+     */
+    title: null,
+    
+    /**
+     * APIProperty: description
+     * {String} Description of this style.
+     */
+    description: null,
+
+    /**
+     * APIProperty: layerName
+     * {<String>} Name of the layer that this style belongs to, usually
+     *     according to the NamedLayer attribute of an SLD document.
+     */
+    layerName: null,
+    
+    /**
+     * APIProperty: isDefault
+     * {Boolean}
+     */
+    isDefault: false,
+     
+    /** 
+     * APIProperty: rules 
+     * {Array(<OpenLayers.Rule>)} Collection of rendering rules.
+     */
+    rules: null,
+    
+    /** 
+     * Constructor: OpenLayers.Style2
+     * Creates a style representing a collection of rendering rules.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     style.  Any documented properties may be set at construction.
+     *
+     * Return:
+     * {<OpenLayers.Style2>} A new style object.
+     */
+    initialize: function(config) {
+        OpenLayers.Util.extend(this, config);
+        this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        for (var i=0, len=this.rules.length; i<len; i++) {
+            this.rules[i].destroy();
+        }
+        delete this.rules;
+    },
+
+    /**
+     * APIMethod: clone
+     * Clones this style.
+     * 
+     * Returns:
+     * {<OpenLayers.Style2>} Clone of this style.
+     */
+    clone: function() {
+        var config = OpenLayers.Util.extend({}, this);
+        // clone rules
+        if (this.rules) {
+            config.rules = [];
+            for (var i=0, len=this.rules.length; i<len; ++i) {
+                config.rules.push(this.rules[i].clone());
+            }
+        }
+        return new OpenLayers.Style2(config);
+    },
+    
+    CLASS_NAME: "OpenLayers.Style2"
+});

Modified: sandbox/ahocevar/playground/lib/OpenLayers/StyleMap.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/StyleMap.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/StyleMap.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Symbolizer/Line.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,74 +0,0 @@
-/* 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/Symbolizer.js
- */
-
-/**
- * Class: OpenLayers.Symbolizer.Line
- * A symbolizer used to render line features.
- */
-OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, {
-
-    /**
-     * APIProperty: strokeColor
-     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
-     *     for red).  
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeOpacity
-     * {Number} Stroke opacity (0-1).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeWidth
-     * {Number} Pixel stroke width.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeLinecap
-     * {String} Stroke cap type ("butt", "round", or "square").
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * Property: strokeDashstyle
-     * {String} Stroke dash style according to the SLD spec. Note that the
-     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
-     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
-     *     most SLD patterns will render correctly in OpenLayers.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * Constructor: OpenLayers.Symbolizer.Line
-     * Create a symbolizer for rendering lines.
-     *
-     * Parameters:
-     * config - {Object} An object containing properties to be set on the 
-     *     symbolizer.  Any documented symbolizer property can be set at 
-     *     construction.
-     *
-     * Returns:
-     * A new line symbolizer.
-     */
-    initialize: function(config) {
-        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
-    },
-    
-    CLASS_NAME: "OpenLayers.Symbolizer.Line"
-    
-});
-

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer/Line.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Line.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,74 @@
+/* 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/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Line
+ * A symbolizer used to render line features.
+ */
+OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, {
+
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).  
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Line
+     * Create a symbolizer for rendering lines.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new line symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Line"
+    
+});
+

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Symbolizer/Point.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,157 +0,0 @@
-/* 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/Symbolizer.js
- */
-
-/**
- * Class: OpenLayers.Symbolizer.Point
- * A symbolizer used to render point features.
- */
-OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, {
-    
-    /**
-     * APIProperty: strokeColor
-     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
-     *     for red).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeOpacity
-     * {Number} Stroke opacity (0-1).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeWidth
-     * {Number} Pixel stroke width.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeLinecap
-     * {String} Stroke cap type ("butt", "round", or "square").
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * Property: strokeDashstyle
-     * {String} Stroke dash style according to the SLD spec. Note that the
-     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
-     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
-     *     most SLD patterns will render correctly in OpenLayers.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * APIProperty: fillColor
-     * {String} RGB hex fill color (e.g. "#ff0000" for red).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: fillOpacity
-     * {Number} Fill opacity (0-1).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * APIProperty: pointRadius
-     * {Number} Pixel point radius.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * APIProperty: externalGraphic
-     * {String} Url to an external graphic that will be used for rendering 
-     *     points.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicWidth
-     * {Number} Pixel width for sizing an external graphic.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicHeight
-     * {Number} Pixel height for sizing an external graphic.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicOpacity
-     * {Number} Opacity (0-1) for an external graphic.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicXOffset
-     * {Number} Pixel offset along the positive x axis for displacing an 
-     *     external graphic.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicYOffset
-     * {Number} Pixel offset along the positive y axis for displacing an 
-     *     external graphic.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * APIProperty: rotation
-     * {Number} The rotation of a graphic in the clockwise direction about its 
-     *     center point (or any point off center as specified by 
-     *     <graphicXOffset> and <graphicYOffset>).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: graphicName
-     * {String} Named graphic to use when rendering points.  Supported values 
-     *     include "circle", "square", "star", "x", "cross", and "triangle".
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * Constructor: OpenLayers.Symbolizer.Point
-     * Create a symbolizer for rendering points.
-     *
-     * Parameters:
-     * config - {Object} An object containing properties to be set on the 
-     *     symbolizer.  Any documented symbolizer property can be set at 
-     *     construction.
-     *
-     * Returns:
-     * A new point symbolizer.
-     */
-    initialize: function(config) {
-        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
-    },
-    
-    CLASS_NAME: "OpenLayers.Symbolizer.Point"
-    
-});
-

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer/Point.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Point.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,157 @@
+/* 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/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Point
+ * A symbolizer used to render point features.
+ */
+OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: fillColor
+     * {String} RGB hex fill color (e.g. "#ff0000" for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: fillOpacity
+     * {Number} Fill opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: pointRadius
+     * {Number} Pixel point radius.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: externalGraphic
+     * {String} Url to an external graphic that will be used for rendering 
+     *     points.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicWidth
+     * {Number} Pixel width for sizing an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicHeight
+     * {Number} Pixel height for sizing an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicOpacity
+     * {Number} Opacity (0-1) for an external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicXOffset
+     * {Number} Pixel offset along the positive x axis for displacing an 
+     *     external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicYOffset
+     * {Number} Pixel offset along the positive y axis for displacing an 
+     *     external graphic.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: rotation
+     * {Number} The rotation of a graphic in the clockwise direction about its 
+     *     center point (or any point off center as specified by 
+     *     <graphicXOffset> and <graphicYOffset>).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: graphicName
+     * {String} Named graphic to use when rendering points.  Supported values 
+     *     include "circle", "square", "star", "x", "cross", and "triangle".
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer.Point
+     * Create a symbolizer for rendering points.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new point symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Point"
+    
+});
+

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Symbolizer/Polygon.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,88 +0,0 @@
-/* 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/Symbolizer.js
- */
-
-/**
- * Class: OpenLayers.Symbolizer.Polygon
- * A symbolizer used to render line features.
- */
-OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, {
-    
-    /**
-     * APIProperty: strokeColor
-     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
-     *     for red).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeOpacity
-     * {Number} Stroke opacity (0-1).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeWidth
-     * {Number} Pixel stroke width.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: strokeLinecap
-     * {String} Stroke cap type ("butt", "round", or "square").
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * Property: strokeDashstyle
-     * {String} Stroke dash style according to the SLD spec. Note that the
-     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
-     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
-     *     most SLD patterns will render correctly in OpenLayers.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * APIProperty: fillColor
-     * {String} RGB hex fill color (e.g. "#ff0000" for red).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * APIProperty: fillOpacity
-     * {Number} Fill opacity (0-1).
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * Constructor: OpenLayers.Symbolizer.Polygon
-     * Create a symbolizer for rendering polygons.
-     *
-     * Parameters:
-     * config - {Object} An object containing properties to be set on the 
-     *     symbolizer.  Any documented symbolizer property can be set at 
-     *     construction.
-     *
-     * Returns:
-     * A new polygon symbolizer.
-     */
-    initialize: function(config) {
-        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
-    },
-    
-    CLASS_NAME: "OpenLayers.Symbolizer.Polygon"
-    
-});
-

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer/Polygon.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Polygon.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,88 @@
+/* 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/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Polygon
+ * A symbolizer used to render line features.
+ */
+OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * APIProperty: strokeColor
+     * {String} Color for line stroke.  This is a RGB hex value (e.g. "#ff0000"
+     *     for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeOpacity
+     * {Number} Stroke opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeWidth
+     * {Number} Pixel stroke width.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: strokeLinecap
+     * {String} Stroke cap type ("butt", "round", or "square").
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: strokeDashstyle
+     * {String} Stroke dash style according to the SLD spec. Note that the
+     *     OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot",
+     *     "longdash", "longdashdot", or "solid") will not work in SLD, but
+     *     most SLD patterns will render correctly in OpenLayers.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * APIProperty: fillColor
+     * {String} RGB hex fill color (e.g. "#ff0000" for red).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * APIProperty: fillOpacity
+     * {Number} Fill opacity (0-1).
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Polygon
+     * Create a symbolizer for rendering polygons.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new polygon symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Polygon"
+    
+});
+

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Symbolizer/Raster.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,34 +0,0 @@
-/* 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/Symbolizer.js
- */
-
-/**
- * Class: OpenLayers.Symbolizer.Raster
- * A symbolizer used to render raster images.
- */
-OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, {
-    
-    /**
-     * Constructor: OpenLayers.Symbolizer.Raster
-     * Create a symbolizer for rendering rasters.
-     *
-     * Parameters:
-     * config - {Object} An object containing properties to be set on the 
-     *     symbolizer.  Any documented symbolizer property can be set at 
-     *     construction.
-     *
-     * Returns:
-     * A new raster symbolizer.
-     */
-    initialize: function(config) {
-        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
-    },
-    
-    CLASS_NAME: "OpenLayers.Symbolizer.Raster"
-    
-});

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer/Raster.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Raster.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,34 @@
+/* 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/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Raster
+ * A symbolizer used to render raster images.
+ */
+OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer.Raster
+     * Create a symbolizer for rendering rasters.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new raster symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Raster"
+    
+});

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Symbolizer/Text.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,70 +0,0 @@
-/* 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/Symbolizer.js
- */
-
-/**
- * Class: OpenLayers.Symbolizer.Text
- * A symbolizer used to render text labels for features.
- */
-OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, {
-    
-    /** 
-     * APIProperty: label
-     * {String} The text for the label.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /** 
-     * APIProperty: fontFamily
-     * {String} The font family for the label.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /** 
-     * APIProperty: fontSize
-     * {String} The font size for the label.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /** 
-     * APIProperty: fontWeight
-     * {String} The font weight for the label.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-    
-    /**
-     * Property: fontStyle
-     * {String} The font style for the label.
-     * 
-     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
-     */
-
-    /**
-     * Constructor: OpenLayers.Symbolizer.Text
-     * Create a symbolizer for rendering text labels.
-     *
-     * Parameters:
-     * config - {Object} An object containing properties to be set on the 
-     *     symbolizer.  Any documented symbolizer property can be set at 
-     *     construction.
-     *
-     * Returns:
-     * A new text symbolizer.
-     */
-    initialize: function(config) {
-        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
-    },
-    
-    CLASS_NAME: "OpenLayers.Symbolizer.Text"
-    
-});
-

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer/Text.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer/Text.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,70 @@
+/* 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/Symbolizer.js
+ */
+
+/**
+ * Class: OpenLayers.Symbolizer.Text
+ * A symbolizer used to render text labels for features.
+ */
+OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, {
+    
+    /** 
+     * APIProperty: label
+     * {String} The text for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /** 
+     * APIProperty: fontFamily
+     * {String} The font family for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /** 
+     * APIProperty: fontSize
+     * {String} The font size for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /** 
+     * APIProperty: fontWeight
+     * {String} The font weight for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+    
+    /**
+     * Property: fontStyle
+     * {String} The font style for the label.
+     * 
+     * No default set here.  Use OpenLayers.Renderer.defaultRenderer for defaults.
+     */
+
+    /**
+     * Constructor: OpenLayers.Symbolizer.Text
+     * Create a symbolizer for rendering text labels.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new text symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer.Text"
+    
+});
+

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Symbolizer.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Symbolizer.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,51 @@
+/* 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. */
+
+/**
+ * Class: OpenLayers.Symbolizer
+ * Base class representing a symbolizer used for feature rendering.
+ */
+OpenLayers.Symbolizer = OpenLayers.Class({
+    
+
+    /**
+     * APIProperty: zIndex
+     * {Number} The zIndex determines the rendering order for a symbolizer.
+     *     Symbolizers with larger zIndex values are rendered over symbolizers
+     *     with smaller zIndex values.  Default is 0.
+     */
+    zIndex: 0,
+    
+    /**
+     * Constructor: OpenLayers.Symbolizer
+     * Instances of this class are not useful.  See one of the subclasses.
+     *
+     * Parameters:
+     * config - {Object} An object containing properties to be set on the 
+     *     symbolizer.  Any documented symbolizer property can be set at 
+     *     construction.
+     *
+     * Returns:
+     * A new symbolizer.
+     */
+    initialize: function(config) {
+        OpenLayers.Util.extend(this, config);
+    },
+    
+    /** 
+     * APIMethod: clone
+     * Create a copy of this symbolizer.
+     *
+     * Returns a symbolizer of the same type with the same properties.
+     */
+    clone: function() {
+        var Type = eval(this.CLASS_NAME);
+        return new Type(OpenLayers.Util.extend({}, this));
+    },
+    
+    CLASS_NAME: "OpenLayers.Symbolizer"
+    
+});
+

Deleted: sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Tile/Image/IFrame.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,224 +0,0 @@
-/* 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/Tile/Image.js
- */
-
-/**
- * Constant: OpenLayers.Tile.Image.IFrame
- * Mixin for tiles that use form-encoded POST requests to get images from
- * remote services. Images will be loaded using HTTP-POST into an IFrame.
- *
- * This mixin will be applied to <OpenLayers.Tile.Image> instances
- * configured with <OpenLayers.Tile.Image.allowPost> or
- * <OpenLayers.Tile.Image.enforcePost> set to true.
- *
- * Inherits from:
- *  - <OpenLayers.Tile.Image>
- */
-OpenLayers.Tile.Image.IFrame = {
-    
-    /**
-     * Property: useIFrame
-     * {Boolean} true if we are currently using an IFrame to render POST
-     * responses, false if we are using an img element to render GET responses.
-     */ 
-    useIFrame: null,
-
-    /**
-     * Method: clear
-     * Removes the iframe from DOM (avoids back-button problems).
-     */
-    clear: function() {
-        if (this.useIFrame) {
-            if (this.imgDiv) {
-                var iFrame = this.imgDiv.firstChild;
-                OpenLayers.Event.stopObservingElement(iFrame);
-                this.imgDiv.removeChild(iFrame);
-                delete iFrame;
-            }
-        } else {
-            OpenLayers.Tile.Image.prototype.clear.apply(this, arguments)
-        }
-    },
-
-    /**
-     * Method: renderTile
-     */
-     renderTile: function() {
-        if (OpenLayers.Tile.Image.prototype.renderTile.apply(this, arguments) &&
-                                                            this.useIFrame) {
-            // create a html form and add it temporary to the layer div
-            var form = this.createRequestForm();
-            this.imgDiv.appendChild(form);
-
-            // submit the form (means fetching the image)
-            form.submit();
-            this.imgDiv.removeChild(form);
-            delete form;
-        }
-        return true;
-    },
-
-    /**
-     * Method: initImgDiv
-     * Creates the imgDiv property on the tile.
-     */
-    initImgDiv: function() {
-        this.useIFrame = this.maxGetUrlLength !== null && !this.layer.async &&
-            this.url.length > this.maxGetUrlLength;
-        if (this.imgDiv != null) {
-            var nodeName = this.imgDiv.nodeName.toLowerCase();
-            if ((this.useIFrame && nodeName == "img") ||
-                                        (!this.useIFrame && nodeName == "div")) {
-                // switch between get and post
-                this.removeImgDiv();
-                this.imgDiv = null;
-            }
-        }
-        if (this.useIFrame) {
-            if (this.imgDiv == null) {
-                var eventPane = document.createElement("div");
-
-                if(OpenLayers.BROWSER_NAME == "msie") {
-                    // IE cannot handle events on elements without backgroundcolor.
-                    // So we use this little hack to make elements transparent
-                    eventPane.style.backgroundColor = '#FFFFFF';
-                    eventPane.style.filter          = 'chroma(color=#FFFFFF)';
-                }
-
-                OpenLayers.Util.modifyDOMElement(eventPane, null,
-                    new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
-
-                this.imgDiv = document.createElement("div");
-                this.imgDiv.appendChild(eventPane);
-
-                OpenLayers.Util.modifyDOMElement(this.imgDiv, this.id, null,
-                    this.layer.getImageSize(), "relative");
-                this.imgDiv.className = 'olTileImage';
-
-                this.frame.appendChild(this.imgDiv); 
-                this.layer.div.appendChild(this.frame); 
-
-                if(this.layer.opacity != null) {
-
-                    OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null,
-                                                     null, null, null, null, 
-                                                     this.layer.opacity);
-                }
-
-                // we need this reference to check back the viewRequestID
-                this.imgDiv.map = this.layer.map;
-            }
-            this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
-
-        } else {
-            OpenLayers.Tile.Image.prototype.initImgDiv.apply(this, arguments);
-        }
-    },
-
-    /**
-     * Method: createIFrame
-     * Create the IFrame which shows the image.
-     *
-     * Returns:
-     * {DOMElement} Iframe
-     */
-    createIFrame: function() {
-        var id = this.id+'_iFrame';
-        var iframe;
-        if(OpenLayers.BROWSER_NAME == "msie") {
-            // InternetExplorer does not set the name attribute of an iFrame 
-            // properly via DOM manipulation, so we need to do it on our own with
-            // this hack.
-            iframe = document.createElement('<iframe name="'+id+'">');
-
-            // IFrames in InternetExplorer are not transparent, if you set the
-            // backgroundColor transparent. This is a workarround to get 
-            // transparent iframes.
-            iframe.style.backgroundColor = '#FFFFFF';
-            iframe.style.filter          = 'chroma(color=#FFFFFF)';
-        }
-        else {
-            iframe = document.createElement('iframe');
-            iframe.style.backgroundColor = 'transparent';
-        
-            // iframe.name needs to be an unique id, otherwise it 
-            // could happen that other iframes are overwritten.
-            iframe.name = id;
-        }
-        iframe.id = id;
-
-        // some special properties to avoid scaling the images and scrollbars 
-        // in the iframe
-        iframe.scrolling             = 'no';
-        iframe.marginWidth           = '0px';
-        iframe.marginHeight          = '0px';
-        iframe.frameBorder           = '0';
-
-        OpenLayers.Util.modifyDOMElement(iframe, id, 
-            new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
-
-        //bind a listener to the onload of the iframe so that we
-        // can register when a tile has finished loading.
-        var onload = function() {
-            this.show();
-            //normally isLoading should always be true here but there are some
-            // right funky conditions where loading and then reloading a tile
-            // with the same url *really*fast*. this check prevents sending
-            // a 'loadend' if the msg has already been sent
-            //
-            if (this.isLoading) {
-                this.isLoading = false;
-                this.events.triggerEvent("loadend");
-            }
-        };
-        OpenLayers.Event.observe(iframe, 'load',
-            OpenLayers.Function.bind(onload, this));
-
-        return iframe;
-    },
-    
-    /**
-     * Method: createRequestForm
-     * Create the html <form> element with width, height, bbox and all 
-     * parameters specified in the layer params.
-     *
-     * Returns: 
-     * {DOMElement} The form element which sends the HTTP-POST request to the
-     *              WMS. 
-     */
-    createRequestForm: function() {
-        // creation of the form element
-        var form = document.createElement('form');
-        form.method = 'POST';
-        var cacheId = this.layer.params["_OLSALT"];
-        cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
-        form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
-
-        // insert the iframe, which has been removed to avoid back-button
-        // problems
-        this.imgDiv.insertBefore(this.createIFrame(), this.imgDiv.firstChild);
-
-        form.target = this.id+'_iFrame';
-
-        // adding all parameters in layer params as hidden fields to the html
-        // form element
-        var imageSize = this.layer.getImageSize();
-        var params = OpenLayers.Util.getParameters(this.url);
-            
-        for(var par in params) {
-            var field = document.createElement('input');
-            field.type  = 'hidden';
-            field.name  = par;
-            field.value = params[par];
-            form.appendChild(field);
-        }   
-
-        return form;
-    }
-}

Copied: sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js (from rev 10919, trunk/openlayers/lib/OpenLayers/Tile/Image/IFrame.js)
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js	                        (rev 0)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image/IFrame.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,224 @@
+/* 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/Tile/Image.js
+ */
+
+/**
+ * Constant: OpenLayers.Tile.Image.IFrame
+ * Mixin for tiles that use form-encoded POST requests to get images from
+ * remote services. Images will be loaded using HTTP-POST into an IFrame.
+ *
+ * This mixin will be applied to <OpenLayers.Tile.Image> instances
+ * configured with <OpenLayers.Tile.Image.allowPost> or
+ * <OpenLayers.Tile.Image.enforcePost> set to true.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Tile.Image>
+ */
+OpenLayers.Tile.Image.IFrame = {
+    
+    /**
+     * Property: useIFrame
+     * {Boolean} true if we are currently using an IFrame to render POST
+     * responses, false if we are using an img element to render GET responses.
+     */ 
+    useIFrame: null,
+
+    /**
+     * Method: clear
+     * Removes the iframe from DOM (avoids back-button problems).
+     */
+    clear: function() {
+        if (this.useIFrame) {
+            if (this.imgDiv) {
+                var iFrame = this.imgDiv.firstChild;
+                OpenLayers.Event.stopObservingElement(iFrame);
+                this.imgDiv.removeChild(iFrame);
+                delete iFrame;
+            }
+        } else {
+            OpenLayers.Tile.Image.prototype.clear.apply(this, arguments)
+        }
+    },
+
+    /**
+     * Method: renderTile
+     */
+     renderTile: function() {
+        if (OpenLayers.Tile.Image.prototype.renderTile.apply(this, arguments) &&
+                                                            this.useIFrame) {
+            // create a html form and add it temporary to the layer div
+            var form = this.createRequestForm();
+            this.imgDiv.appendChild(form);
+
+            // submit the form (means fetching the image)
+            form.submit();
+            this.imgDiv.removeChild(form);
+            delete form;
+        }
+        return true;
+    },
+
+    /**
+     * Method: initImgDiv
+     * Creates the imgDiv property on the tile.
+     */
+    initImgDiv: function() {
+        this.useIFrame = this.maxGetUrlLength !== null && !this.layer.async &&
+            this.url.length > this.maxGetUrlLength;
+        if (this.imgDiv != null) {
+            var nodeName = this.imgDiv.nodeName.toLowerCase();
+            if ((this.useIFrame && nodeName == "img") ||
+                                        (!this.useIFrame && nodeName == "div")) {
+                // switch between get and post
+                this.removeImgDiv();
+                this.imgDiv = null;
+            }
+        }
+        if (this.useIFrame) {
+            if (this.imgDiv == null) {
+                var eventPane = document.createElement("div");
+
+                if(OpenLayers.BROWSER_NAME == "msie") {
+                    // IE cannot handle events on elements without backgroundcolor.
+                    // So we use this little hack to make elements transparent
+                    eventPane.style.backgroundColor = '#FFFFFF';
+                    eventPane.style.filter          = 'chroma(color=#FFFFFF)';
+                }
+
+                OpenLayers.Util.modifyDOMElement(eventPane, null,
+                    new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
+
+                this.imgDiv = document.createElement("div");
+                this.imgDiv.appendChild(eventPane);
+
+                OpenLayers.Util.modifyDOMElement(this.imgDiv, this.id, null,
+                    this.layer.getImageSize(), "relative");
+                this.imgDiv.className = 'olTileImage';
+
+                this.frame.appendChild(this.imgDiv); 
+                this.layer.div.appendChild(this.frame); 
+
+                if(this.layer.opacity != null) {
+
+                    OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null,
+                                                     null, null, null, null, 
+                                                     this.layer.opacity);
+                }
+
+                // we need this reference to check back the viewRequestID
+                this.imgDiv.map = this.layer.map;
+            }
+            this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
+
+        } else {
+            OpenLayers.Tile.Image.prototype.initImgDiv.apply(this, arguments);
+        }
+    },
+
+    /**
+     * Method: createIFrame
+     * Create the IFrame which shows the image.
+     *
+     * Returns:
+     * {DOMElement} Iframe
+     */
+    createIFrame: function() {
+        var id = this.id+'_iFrame';
+        var iframe;
+        if(OpenLayers.BROWSER_NAME == "msie") {
+            // InternetExplorer does not set the name attribute of an iFrame 
+            // properly via DOM manipulation, so we need to do it on our own with
+            // this hack.
+            iframe = document.createElement('<iframe name="'+id+'">');
+
+            // IFrames in InternetExplorer are not transparent, if you set the
+            // backgroundColor transparent. This is a workarround to get 
+            // transparent iframes.
+            iframe.style.backgroundColor = '#FFFFFF';
+            iframe.style.filter          = 'chroma(color=#FFFFFF)';
+        }
+        else {
+            iframe = document.createElement('iframe');
+            iframe.style.backgroundColor = 'transparent';
+        
+            // iframe.name needs to be an unique id, otherwise it 
+            // could happen that other iframes are overwritten.
+            iframe.name = id;
+        }
+        iframe.id = id;
+
+        // some special properties to avoid scaling the images and scrollbars 
+        // in the iframe
+        iframe.scrolling             = 'no';
+        iframe.marginWidth           = '0px';
+        iframe.marginHeight          = '0px';
+        iframe.frameBorder           = '0';
+
+        OpenLayers.Util.modifyDOMElement(iframe, id, 
+            new OpenLayers.Pixel(0,0), this.layer.getImageSize(), "absolute");
+
+        //bind a listener to the onload of the iframe so that we
+        // can register when a tile has finished loading.
+        var onload = function() {
+            this.show();
+            //normally isLoading should always be true here but there are some
+            // right funky conditions where loading and then reloading a tile
+            // with the same url *really*fast*. this check prevents sending
+            // a 'loadend' if the msg has already been sent
+            //
+            if (this.isLoading) {
+                this.isLoading = false;
+                this.events.triggerEvent("loadend");
+            }
+        };
+        OpenLayers.Event.observe(iframe, 'load',
+            OpenLayers.Function.bind(onload, this));
+
+        return iframe;
+    },
+    
+    /**
+     * Method: createRequestForm
+     * Create the html <form> element with width, height, bbox and all 
+     * parameters specified in the layer params.
+     *
+     * Returns: 
+     * {DOMElement} The form element which sends the HTTP-POST request to the
+     *              WMS. 
+     */
+    createRequestForm: function() {
+        // creation of the form element
+        var form = document.createElement('form');
+        form.method = 'POST';
+        var cacheId = this.layer.params["_OLSALT"];
+        cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
+        form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
+
+        // insert the iframe, which has been removed to avoid back-button
+        // problems
+        this.imgDiv.insertBefore(this.createIFrame(), this.imgDiv.firstChild);
+
+        form.target = this.id+'_iFrame';
+
+        // adding all parameters in layer params as hidden fields to the html
+        // form element
+        var imageSize = this.layer.getImageSize();
+        var params = OpenLayers.Util.getParameters(this.url);
+            
+        for(var par in params) {
+            var field = document.createElement('input');
+            field.type  = 'hidden';
+            field.name  = par;
+            field.value = params[par];
+            form.appendChild(field);
+        }   
+
+        return form;
+    }
+}

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tile/Image.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -75,7 +76,24 @@
      *     effects when the tile is moved or changes resolution.
      */
     backBufferTile: null,
-
+    
+    /**
+     * APIProperty: maxGetUrlLength
+     * {Number} If set, requests that would result in GET urls with more
+     * characters than the number provided will be made using form-encoded
+     * HTTP POST. It is good practice to avoid urls that are longer than 2048
+     * characters.
+     *
+     * Caution:
+     * Older versions of Gecko based browsers (e.g. Firefox < 3.5) and
+     * Opera < 10.0 do not fully support this option.
+     *
+     * Note:
+     * Do not use this option for layers that have a transitionEffect
+     * configured - IFrame tiles from POST requests can not be resized.
+     */
+    maxGetUrlLength: null,
+    
     /** TBD 3.0 - reorder the parameters to the init function to remove 
      *             URL. the getUrl() function on the layer gets called on 
      *             each draw(), so no need to specify it here.
@@ -89,17 +107,22 @@
      * bounds - {<OpenLayers.Bounds>}
      * url - {<String>} Deprecated. Remove me in 3.0.
      * size - {<OpenLayers.Size>}
+     * options - {Object}
      */   
-    initialize: function(layer, position, bounds, url, size) {
+    initialize: function(layer, position, bounds, url, size, options) {
         OpenLayers.Tile.prototype.initialize.apply(this, arguments);
 
+        if (this.maxGetUrlLength != null) {
+            OpenLayers.Util.extend(this, OpenLayers.Tile.Image.IFrame);
+        }
+
         this.url = url; //deprecated remove me
         
         this.frame = document.createElement('div'); 
         this.frame.style.overflow = 'hidden'; 
         this.frame.style.position = 'absolute'; 
 
-        this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack();
+        this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack();        
     },
 
     /** 
@@ -108,22 +131,7 @@
      */
     destroy: function() {
         if (this.imgDiv != null)  {
-            if (this.layerAlphaHack) {
-                // unregister the "load" handler
-                OpenLayers.Event.stopObservingElement(this.imgDiv.childNodes[0].id);                
-            }
-
-            // unregister the "load" and "error" handlers. Only the "error" handler if
-            // this.layerAlphaHack is true.
-            OpenLayers.Event.stopObservingElement(this.imgDiv.id);
-            
-            if (this.imgDiv.parentNode == this.frame) {
-                this.frame.removeChild(this.imgDiv);
-                this.imgDiv.map = null;
-            }
-            this.imgDiv.urls = null;
-            // abort any currently loading image
-            this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
+            this.removeImgDiv();
         }
         this.imgDiv = null;
         if ((this.frame != null) && (this.frame.parentNode == this.layer.div)) { 
@@ -141,7 +149,7 @@
         
         OpenLayers.Tile.prototype.destroy.apply(this, arguments);
     },
-
+    
     /**
      * Method: clone
      *
@@ -183,7 +191,8 @@
         }
         var drawTile = OpenLayers.Tile.prototype.draw.apply(this, arguments);
         
-        if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) {
+        if ((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) || 
+            this.layer.singleTile) {
             if (drawTile) {
                 //we use a clone of this tile to create a double buffer for visual
                 //continuity.  The backBufferTile is used to create transition
@@ -263,7 +272,7 @@
                 this.backBufferTile.position = this.position;
                 this.backBufferTile.bounds = this.bounds;
                 this.backBufferTile.size = this.size;
-                this.backBufferTile.imageSize = this.layer.imageSize || this.size;
+                this.backBufferTile.imageSize = this.layer.getImageSize(this.bounds) || this.size;
                 this.backBufferTile.imageOffset = this.layer.imageOffset;
                 this.backBufferTile.resolution = this.layer.getResolution();
                 this.backBufferTile.renderTile();
@@ -279,13 +288,8 @@
      *     position it correctly, and set its url.
      */
     renderTile: function() {
-        if (this.imgDiv == null) {
+        if (this.layer.async) {
             this.initImgDiv();
-        }
-
-        this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
-        
-        if (this.layer.async) {
             // Asyncronous image requests call the asynchronous getURL method
             // on the layer to fetch an image that covers 'this.bounds', in the scope of
             // 'this', setting the 'url' property of the layer itself, and running
@@ -295,12 +299,9 @@
             // syncronous image requests get the url and position the frame immediately,
             // and don't wait for an image request to come back.
           
-            // needed for changing to a different server for onload error
-            if (this.layer.url instanceof Array) {
-                this.imgDiv.urls = this.layer.url.slice();
-            }
-          
             this.url = this.layer.getURL(this.bounds);
+
+            this.initImgDiv();
           
             // position the frame immediately
             this.positionImage(); 
@@ -317,14 +318,14 @@
      positionImage: function() {
         // if the this layer doesn't exist at the point the image is
         // returned, do not attempt to use it for size computation
-        if ( this.layer == null )
+        if (this.layer === null) {
             return;
-        
+        }
         // position the frame 
         OpenLayers.Util.modifyDOMElement(this.frame, 
                                           null, this.position, this.size);   
 
-        var imageSize = this.layer.getImageSize(); 
+        var imageSize = this.layer.getImageSize(this.bounds); 
         if (this.layerAlphaHack) {
             OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,
                     null, null, imageSize, this.url);
@@ -354,94 +355,129 @@
      * Creates the imgDiv property on the tile.
      */
     initImgDiv: function() {
-        
-        var offset = this.layer.imageOffset; 
-        var size = this.layer.getImageSize(); 
-     
-        if (this.layerAlphaHack) {
-            this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
-                                                           offset,
-                                                           size,
-                                                           null,
-                                                           "relative",
-                                                           null,
-                                                           null,
-                                                           null,
-                                                           true);
-        } else {
-            this.imgDiv = OpenLayers.Util.createImage(null,
-                                                      offset,
-                                                      size,
-                                                      null,
-                                                      "relative",
-                                                      null,
-                                                      null,
-                                                      true);
-        }
-        
-        this.imgDiv.className = 'olTileImage';
+        if (this.imgDiv == null) {
+            var offset = this.layer.imageOffset; 
+            var size = this.layer.getImageSize(this.bounds); 
 
-        /* checkImgURL used to be used to called as a work around, but it
-           ended up hiding problems instead of solving them and broke things
-           like relative URLs. See discussion on the dev list:
-           http://openlayers.org/pipermail/dev/2007-January/000205.html
+            if (this.layerAlphaHack) {
+                this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
+                                                               offset,
+                                                               size,
+                                                               null,
+                                                               "relative",
+                                                               null,
+                                                               null,
+                                                               null,
+                                                               true);
+            } else {
+                this.imgDiv = OpenLayers.Util.createImage(null,
+                                                          offset,
+                                                          size,
+                                                          null,
+                                                          "relative",
+                                                          null,
+                                                          null,
+                                                          true);
+            }
 
-        OpenLayers.Event.observe( this.imgDiv, "load",
-            OpenLayers.Function.bind(this.checkImgURL, this) );
-        */
-        this.frame.style.zIndex = this.isBackBuffer ? 0 : 1;
-        this.frame.appendChild(this.imgDiv); 
-        this.layer.div.appendChild(this.frame); 
+            // needed for changing to a different server for onload error
+            if (this.layer.url instanceof Array) {
+                this.imgDiv.urls = this.layer.url.slice();
+            }
+      
+            this.imgDiv.className = 'olTileImage';
 
-        if(this.layer.opacity != null) {
-            
-            OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, null,
-                                             null, null, null, 
-                                             this.layer.opacity);
-        }
+            /* checkImgURL used to be used to called as a work around, but it
+               ended up hiding problems instead of solving them and broke things
+               like relative URLs. See discussion on the dev list:
+               http://openlayers.org/pipermail/dev/2007-January/000205.html
 
-        // we need this reference to check back the viewRequestID
-        this.imgDiv.map = this.layer.map;
+            OpenLayers.Event.observe( this.imgDiv, "load",
+                OpenLayers.Function.bind(this.checkImgURL, this) );
+            */
+            this.frame.style.zIndex = this.isBackBuffer ? 0 : 1;
+            this.frame.appendChild(this.imgDiv); 
+            this.layer.div.appendChild(this.frame); 
 
-        //bind a listener to the onload of the image div so that we 
-        // can register when a tile has finished loading.
-        var onload = function() {
-            
-            //normally isLoading should always be true here but there are some 
-            // right funky conditions where loading and then reloading a tile
-            // with the same url *really*fast*. this check prevents sending 
-            // a 'loadend' if the msg has already been sent
-            //
-            if (this.isLoading) { 
-                this.isLoading = false; 
-                this.events.triggerEvent("loadend"); 
+            if(this.layer.opacity != null) {
+
+                OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, null,
+                                                 null, null, null, 
+                                                 this.layer.opacity);
             }
-        };
+
+            // we need this reference to check back the viewRequestID
+            this.imgDiv.map = this.layer.map;
+
+            //bind a listener to the onload of the image div so that we 
+            // can register when a tile has finished loading.
+            var onload = function() {
+
+                //normally isLoading should always be true here but there are some 
+                // right funky conditions where loading and then reloading a tile
+                // with the same url *really*fast*. this check prevents sending 
+                // a 'loadend' if the msg has already been sent
+                //
+                if (this.isLoading) { 
+                    this.isLoading = false; 
+                    this.events.triggerEvent("loadend"); 
+                }
+            };
+
+            if (this.layerAlphaHack) { 
+                OpenLayers.Event.observe(this.imgDiv.childNodes[0], 'load', 
+                                         OpenLayers.Function.bind(onload, this));    
+            } else { 
+                OpenLayers.Event.observe(this.imgDiv, 'load', 
+                                     OpenLayers.Function.bind(onload, this)); 
+            } 
+
+
+            // Bind a listener to the onerror of the image div so that we
+            // can registere when a tile has finished loading with errors.
+            var onerror = function() {
+
+                // If we have gone through all image reload attempts, it is time
+                // to realize that we are done with this image. Since
+                // OpenLayers.Util.onImageLoadError already has taken care about
+                // the error, we can continue as if the image was loaded
+                // successfully.
+                if (this.imgDiv._attempts > OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
+                    onload.call(this);
+                }
+            };
+            OpenLayers.Event.observe(this.imgDiv, "error",
+                                     OpenLayers.Function.bind(onerror, this));
+        }
         
-        if (this.layerAlphaHack) { 
-            OpenLayers.Event.observe(this.imgDiv.childNodes[0], 'load', 
-                                     OpenLayers.Function.bind(onload, this));    
-        } else { 
-            OpenLayers.Event.observe(this.imgDiv, 'load', 
-                                 OpenLayers.Function.bind(onload, this)); 
-        } 
+        this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
+    },
+
+    /**
+     * Method: removeImgDiv
+     * Removes the imgDiv from the DOM and stops listening to events on it.
+     */
+    removeImgDiv: function() {
+        // unregister the "load" and "error" handlers. Only the "error" handler if
+        // this.layerAlphaHack is true.
+        OpenLayers.Event.stopObservingElement(this.imgDiv);
         
+        if (this.imgDiv.parentNode == this.frame) {
+            this.frame.removeChild(this.imgDiv);
+            this.imgDiv.map = null;
+        }
+        this.imgDiv.urls = null;
 
-        // Bind a listener to the onerror of the image div so that we
-        // can registere when a tile has finished loading with errors.
-        var onerror = function() {
-
-            // If we have gone through all image reload attempts, it is time
-            // to realize that we are done with this image. Since
-            // OpenLayers.Util.onImageLoadError already has taken care about
-            // the error, we can continue as if the image was loaded
-            // successfully.
-            if (this.imgDiv._attempts > OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
-                onload.call(this);
-            }
-        };
-        OpenLayers.Event.observe(this.imgDiv, "error",
-                                 OpenLayers.Function.bind(onerror, this));
+        var child = this.imgDiv.firstChild;
+        //check for children (alphaHack img or IFrame)
+        if (child) {
+            OpenLayers.Event.stopObservingElement(child);
+            this.imgDiv.removeChild(child);
+            delete child;
+        } else {
+            // abort any currently loading image
+            this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
+        }
     },
 
     /**
@@ -553,7 +589,7 @@
         // before continuing execution.
         if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, 
                 this.layer.transitionEffect) != -1) {
-            if (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) { 
+            if (OpenLayers.IS_GECKO === true) { 
                 this.frame.scrollLeft = this.frame.scrollLeft; 
             } 
         }
@@ -572,5 +608,5 @@
 );
 
 OpenLayers.Tile.Image.useBlankTile = ( 
-    OpenLayers.Util.getBrowserName() == "safari" || 
-    OpenLayers.Util.getBrowserName() == "opera"); 
+    OpenLayers.BROWSER_NAME == "safari" || 
+    OpenLayers.BROWSER_NAME == "opera"); 

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Tile/WFS.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Tile/WFS.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tile/WFS.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
  

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Tile.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Tile.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tile.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 
@@ -93,8 +94,9 @@
      * bounds - {<OpenLayers.Bounds>}
      * url - {<String>}
      * size - {<OpenLayers.Size>}
+     * options - {Object}
      */   
-    initialize: function(layer, position, bounds, url, size) {
+    initialize: function(layer, position, bounds, url, size, options) {
         this.layer = layer;
         this.position = position.clone();
         this.bounds = bounds.clone();
@@ -105,6 +107,8 @@
         this.id = OpenLayers.Util.createUniqueID("Tile_");
         
         this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
+
+        OpenLayers.Util.extend(this, options);
     },
 
     /**

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Tween.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Tween.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Tween.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -148,12 +149,7 @@
         }
         
         if (this.time > this.duration) {
-            if (this.callbacks && this.callbacks.done) {
-                this.callbacks.done.call(this, this.finish);
-                this.playing = false;
-            }
-            window.clearInterval(this.interval);
-            this.interval = null;
+            this.stop();
         }
     },
     

Modified: sandbox/ahocevar/playground/lib/OpenLayers/Util.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers/Util.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers/Util.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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. */
 
 /**
@@ -31,6 +32,20 @@
     return elements;
 };
 
+/**
+ * Function: isElement
+ * A cross-browser implementation of "e instanceof Element".
+ *
+ * Parameters:
+ * o - {Object} The object to test.
+ *
+ * Returns:
+ * {Boolean}
+ */
+OpenLayers.Util.isElement = function(o) {
+    return !!(o && o.nodeType === 1);
+};
+
 /** 
  * Maintain existing definition of $.
  */
@@ -133,17 +148,21 @@
  * obj - {Object}
  * 
  * Returns:
- * {Integer} The index at, which the object was found in the array.
+ * {Integer} The index at, which the first object was found in the array.
  *           If not found, returns -1.
  */
 OpenLayers.Util.indexOf = function(array, obj) {
-
-    for(var i=0, len=array.length; i<len; i++) {
-        if (array[i] == obj) {
-            return i;
+    // use the build-in function if available.
+    if (typeof array.indexOf == "function") {
+        return array.indexOf(obj);
+    } else {
+        for (var i = 0, len = array.length; i < len; i++) {
+            if (array[i] == obj) {
+                return i;
+            }
         }
+        return -1;   
     }
-    return -1;   
 };
 
 
@@ -342,19 +361,12 @@
     //
     if (!this.viewRequestID ||
         (this.map && this.viewRequestID == this.map.viewRequestID)) { 
-        this.style.backgroundColor ="transparent";
         this.style.display = "";  
     }
+    OpenLayers.Element.removeClass(this, "olImageLoadError");
 };
 
 /**
- * Property: onImageLoadErrorColor
- * {String} The color tiles with load errors will turn.
- *          Default is "pink"
- */
-OpenLayers.Util.onImageLoadErrorColor = "pink";
-
-/**
  * Property: IMAGE_RELOAD_ATTEMPTS
  * {Integer} How many times should we try to reload an image before giving up?
  *           Default is 0
@@ -388,7 +400,7 @@
             this.src = this.src;
         }
     } else {
-        this.style.backgroundColor = OpenLayers.Util.onImageLoadErrorColor;
+        OpenLayers.Element.addClass(this, "olImageLoadError");
     }
     this.style.display = "";
 };
@@ -608,8 +620,12 @@
         if (typeof value == 'object' && value.constructor == Array) {
           /* value is an array; encode items and separate with "," */
           var encodedItemArray = [];
+          var item;
           for (var itemIndex=0, len=value.length; itemIndex<len; itemIndex++) {
-            encodedItemArray.push(encodeURIComponent(value[itemIndex]));
+            item = value[itemIndex];
+            encodedItemArray.push(encodeURIComponent(
+                (item === null || item === undefined) ? "" : item)
+            );
           }
           encodedValue = encodedItemArray.join(",");
         }
@@ -625,6 +641,30 @@
 };
 
 /**
+ * Function: urlAppend
+ * Appends a parameter string to a url. This function includes the logic for
+ * using the appropriate character (none, & or ?) to append to the url before
+ * appending the param string.
+ * 
+ * Parameters:
+ * url - {String} The url to append to
+ * paramStr - {String} The param string to append
+ * 
+ * Returns:
+ * {String} The new url
+ */
+OpenLayers.Util.urlAppend = function(url, paramStr) {
+    var newUrl = url;
+    if(paramStr) {
+        var parts = (url + " ").split(/[?&]/);
+        newUrl += (parts.pop() === " " ?
+            paramStr :
+            parts.length ? "&" + paramStr : "?" + paramStr);
+    }
+    return newUrl;
+};
+
+/**
  * Property: ImgPath
  * {String} Default is ''.
  */
@@ -853,22 +893,45 @@
 OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
 
 /**
- * Function: distVincenty
+ * Function: deg
+ *
+ * Parameters:
+ * x - {Float}
+ *
+ * Returns:
+ * {Float}
+ */
+OpenLayers.Util.deg = function(x) {return x*180/Math.PI;};
+
+/**
+ * Property: VincentyConstants
+ * {Object} Constants for Vincenty functions.
+ */
+OpenLayers.Util.VincentyConstants = {
+    a: 6378137,
+    b: 6356752.3142,
+    f: 1/298.257223563
+};
+
+/**
+ * APIFunction: distVincenty
  * Given two objects representing points with geographic coordinates, this
  *     calculates the distance between those points on the surface of an
  *     ellipsoid.
- * 
+ *
  * Parameters:
  * p1 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
  * p2 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
- * 
+ *
  * Returns:
  * {Float} The distance (in km) between the two input points as measured on an
  *     ellipsoid.  Note that the input point objects must be in geographic
  *     coordinates (decimal degrees) and the return distance is in kilometers.
  */
-OpenLayers.Util.distVincenty=function(p1, p2) {
-    var a = 6378137, b = 6356752.3142,  f = 1/298.257223563;
+OpenLayers.Util.distVincenty = function(p1, p2) {
+    var ct = OpenLayers.Util.VincentyConstants;
+    var a = ct.a, b = ct.b, f = ct.f;
+
     var L = OpenLayers.Util.rad(p2.lon - p1.lon);
     var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
     var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
@@ -907,6 +970,68 @@
 };
 
 /**
+ * APIFunction: destinationVincenty
+ * Calculate destination point given start point lat/long (numeric degrees),
+ * bearing (numeric degrees) & distance (in m).
+ * Adapted from Chris Veness work, see
+ * http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html
+ *
+ * Parameters:
+ * lonlat  - {<OpenLayers.LonLat>} (or any object with both .lat, .lon
+ *     properties) The start point.
+ * brng     - {Float} The bearing (degrees).
+ * distance - {Float} The ground distance (meters).
+ *
+ * Returns:
+ * {<OpenLayers.LonLat>} The destination point.
+ */
+OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {
+    var u = OpenLayers.Util;
+    var ct = u.VincentyConstants;
+    var a = ct.a, b = ct.b, f = ct.f;
+
+    var lon1 = lonlat.lon;
+    var lat1 = lonlat.lat;
+
+    var s = dist;
+    var alpha1 = u.rad(brng);
+    var sinAlpha1 = Math.sin(alpha1);
+    var cosAlpha1 = Math.cos(alpha1);
+
+    var tanU1 = (1-f) * Math.tan(u.rad(lat1));
+    var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
+    var sigma1 = Math.atan2(tanU1, cosAlpha1);
+    var sinAlpha = cosU1 * sinAlpha1;
+    var cosSqAlpha = 1 - sinAlpha*sinAlpha;
+    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
+    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
+    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
+
+    var sigma = s / (b*A), sigmaP = 2*Math.PI;
+    while (Math.abs(sigma-sigmaP) > 1e-12) {
+        var cos2SigmaM = Math.cos(2*sigma1 + sigma);
+        var sinSigma = Math.sin(sigma);
+        var cosSigma = Math.cos(sigma);
+        var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+            B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
+        sigmaP = sigma;
+        sigma = s / (b*A) + deltaSigma;
+    }
+
+    var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
+    var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
+        (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
+    var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
+    var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
+    var L = lambda - (1-C) * f * sinAlpha *
+        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
+
+    var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
+
+    return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
+};
+
+/**
  * Function: getParameters
  * Parse the parameters from a URL or from the current page itself into a 
  *     JavaScript Object. Note that parameter values with commas are separated
@@ -931,21 +1056,32 @@
                     url.indexOf('#') : url.length;
         paramsString = url.substring(start, end);
     }
-        
+
     var parameters = {};
     var pairs = paramsString.split(/[&;]/);
     for(var i=0, len=pairs.length; i<len; ++i) {
         var keyValue = pairs[i].split('=');
         if (keyValue[0]) {
-            var key = decodeURIComponent(keyValue[0]);
-            var value = keyValue[1] || ''; //empty string if no value
 
-            //decode individual values
-            value = value.split(",");
-            for(var j=0, jlen=value.length; j<jlen; j++) {
-                value[j] = decodeURIComponent(value[j]);
+            var key = keyValue[0];
+            try {
+                key = decodeURIComponent(key);
+            } catch (err) {
+                key = unescape(key);
             }
+            
+            // being liberal by replacing "+" with " "
+            var value = (keyValue[1] || '').replace(/\+/g, " ");
 
+            try {
+                value = decodeURIComponent(value);
+            } catch (err) {
+                value = unescape(value);
+            }
+            
+            // follow OGC convention of comma delimited values
+            value = value.split(",")
+
             //if there's only one value, do not return as array                    
             if (value.length == 1) {
                 value = value[0];
@@ -1143,18 +1279,19 @@
  * 
  * Returns:
  * {Float} The corresponding resolution given passed-in scale and unit 
- *         parameters.
+ *     parameters.  If the given scale is falsey, the returned resolution will
+ *     be undefined.
  */
 OpenLayers.Util.getResolutionFromScale = function (scale, units) {
-
-    if (units == null) {
-        units = "degrees";
+    var resolution;
+    if (scale) {
+        if (units == null) {
+            units = "degrees";
+        }
+        var normScale = OpenLayers.Util.normalizeScale(scale);
+        resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
+                                        * OpenLayers.DOTS_PER_INCH);        
     }
-
-    var normScale = OpenLayers.Util.normalizeScale(scale);
-
-    var resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
-                                    * OpenLayers.DOTS_PER_INCH);
     return resolution;
 };
 
@@ -1199,51 +1336,142 @@
 
 /**
  * Function: pagePositon
- * Calculates the position of an element on the page. 
+ * Calculates the position of an element on the page (see
+ * http://code.google.com/p/doctype/wiki/ArticlePageOffset)
  *
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
  * Parameters:
  * forElement - {DOMElement}
  * 
  * Returns:
- * {Array} two item array, L value then T value.
+ * {Array} two item array, Left value then Top value.
  */
-OpenLayers.Util.pagePosition = function(forElement) {
-    var valueT = 0, valueL = 0;
+OpenLayers.Util.pagePosition =  function(forElement) {
+    // NOTE: If element is hidden (display none or disconnected or any the
+    // ancestors are hidden) we get (0,0) by default but we still do the
+    // accumulation of scroll position.
 
-    var element = forElement;
-    var child = forElement;
-    while(element) {
+    var pos = [0, 0];
+    var viewportElement = OpenLayers.Util.getViewportElement();
+    if (!forElement || forElement == window || forElement == viewportElement) {
+        // viewport is always at 0,0 as that defined the coordinate system for
+        // this function - this avoids special case checks in the code below
+        return pos;
+    }
 
-        if(element == document.body) {
-            if(OpenLayers.Element.getStyle(child, 'position') == 'absolute') {
-                break;
+    // Gecko browsers normally use getBoxObjectFor to calculate the position.
+    // When invoked for an element with an implicit absolute position though it
+    // can be off by one. Therefore the recursive implementation is used in
+    // those (relatively rare) cases.
+    var BUGGY_GECKO_BOX_OBJECT =
+        OpenLayers.IS_GECKO && document.getBoxObjectFor &&
+        OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' &&
+        (forElement.style.top == '' || forElement.style.left == '');
+
+    var parent = null;
+    var box;
+
+    if (forElement.getBoundingClientRect) { // IE
+        box = forElement.getBoundingClientRect();
+        var scrollTop = viewportElement.scrollTop;
+        var scrollLeft = viewportElement.scrollLeft;
+
+        pos[0] = box.left + scrollLeft;
+        pos[1] = box.top + scrollTop;
+
+    } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko
+        // Gecko ignores the scroll values for ancestors, up to 1.9.  See:
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
+
+        box = document.getBoxObjectFor(forElement);
+        var vpBox = document.getBoxObjectFor(viewportElement);
+        pos[0] = box.screenX - vpBox.screenX;
+        pos[1] = box.screenY - vpBox.screenY;
+
+    } else { // safari/opera
+        pos[0] = forElement.offsetLeft;
+        pos[1] = forElement.offsetTop;
+        parent = forElement.offsetParent;
+        if (parent != forElement) {
+            while (parent) {
+                pos[0] += parent.offsetLeft;
+                pos[1] += parent.offsetTop;
+                parent = parent.offsetParent;
             }
         }
-        
-        valueT += element.offsetTop  || 0;
-        valueL += element.offsetLeft || 0;
 
-        child = element;
-        try {
-            // wrapping this in a try/catch because IE chokes on the offsetParent
-            element = element.offsetParent;
-        } catch(e) {
-            OpenLayers.Console.error(OpenLayers.i18n(
-                                  "pagePositionFailed",{'elemId':element.id}));
-            break;
+        var browser = OpenLayers.BROWSER_NAME;
+
+        // opera & (safari absolute) incorrectly account for body offsetTop
+        if (browser == "opera" || (browser == "safari" &&
+              OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) {
+            pos[1] -= document.body.offsetTop;
         }
-    }
 
-    element = forElement;
-    while(element) {
-        valueT -= element.scrollTop  || 0;
-        valueL -= element.scrollLeft || 0;
-        element = element.parentNode;
+        // accumulate the scroll positions for everything but the body element
+        parent = forElement.offsetParent;
+        while (parent && parent != document.body) {
+            pos[0] -= parent.scrollLeft;
+            // see https://bugs.opera.com/show_bug.cgi?id=249965
+            if (browser != "opera" || parent.tagName != 'TR') {
+                pos[1] -= parent.scrollTop;
+            }
+            parent = parent.offsetParent;
+        }
     }
     
-    return [valueL, valueT];
+    return pos;
 };
 
+/**
+ * Function: getViewportElement
+ * Returns die viewport element of the document. The viewport element is
+ * usually document.documentElement, except in IE,where it is either
+ * document.body or document.documentElement, depending on the document's
+ * compatibility mode (see
+ * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement)
+ */
+OpenLayers.Util.getViewportElement = function() {
+    var viewportElement = arguments.callee.viewportElement;
+    if (viewportElement == undefined) {
+        viewportElement = (OpenLayers.BROWSER_NAME == "msie" &&
+            document.compatMode != 'CSS1Compat') ? document.body :
+            document.documentElement;
+        arguments.callee.viewportElement = viewportElement;
+    }
+    return viewportElement;
+};
 
 /** 
  * Function: isEquivalentUrl
@@ -1403,8 +1631,46 @@
     return head;
 };
 
+/**
+ * Constant: IS_GECKO
+ * {Boolean} True if the userAgent reports the browser to use the Gecko engine
+ */
+OpenLayers.IS_GECKO = (function() {
+    var ua = navigator.userAgent.toLowerCase();
+    return ua.indexOf("webkit") == -1 && ua.indexOf("gecko") != -1;
+})();
 
 /**
+ * Constant: BROWSER_NAME
+ * {String}
+ * A substring of the navigator.userAgent property.  Depending on the userAgent
+ *     property, this will be the empty string or one of the following:
+ *     * "opera" -- Opera
+ *     * "msie"  -- Internet Explorer
+ *     * "safari" -- Safari
+ *     * "firefox" -- FireFox
+ *     * "mozilla" -- Mozilla
+ */
+OpenLayers.BROWSER_NAME = (function() {
+    var name = "";
+    var ua = navigator.userAgent.toLowerCase();
+    if (ua.indexOf("opera") != -1) {
+        name = "opera";
+    } else if (ua.indexOf("msie") != -1) {
+        name = "msie";
+    } else if (ua.indexOf("safari") != -1) {
+        name = "safari";
+    } else if (ua.indexOf("mozilla") != -1) {
+        if (ua.indexOf("firefox") != -1) {
+            name = "firefox";
+        } else {
+            name = "mozilla";
+        }
+    }
+    return name;
+})();
+
+/**
  * Function: getBrowserName
  * 
  * Returns:
@@ -1422,29 +1688,9 @@
  *           return an empty string.
  */
 OpenLayers.Util.getBrowserName = function() {
-    var browserName = "";
-    
-    var ua = navigator.userAgent.toLowerCase();
-    if ( ua.indexOf( "opera" ) != -1 ) {
-        browserName = "opera";
-    } else if ( ua.indexOf( "msie" ) != -1 ) {
-        browserName = "msie";
-    } else if ( ua.indexOf( "safari" ) != -1 ) {
-        browserName = "safari";
-    } else if ( ua.indexOf( "mozilla" ) != -1 ) {
-        if ( ua.indexOf( "firefox" ) != -1 ) {
-            browserName = "firefox";
-        } else {
-            browserName = "mozilla";
-        }
-    }
-    
-    return browserName;
+    return OpenLayers.BROWSER_NAME;
 };
 
-
-
-    
 /**
  * Method: getRenderedDimensions
  * Renders the contentHTML offscreen to determine actual dimensions for
@@ -1614,3 +1860,61 @@
 
     return scrollbarWidth;
 };
+
+/**
+ * APIFunction: getFormattedLonLat
+ * This function will return latitude or longitude value formatted as 
+ *
+ * Parameters:
+ * coordinate - {Float} the coordinate value to be formatted
+ * axis - {String} value of either 'lat' or 'lon' to indicate which axis is to
+ *          to be formatted (default = lat)
+ * dmsOption - {String} specify the precision of the output can be one of:
+ *           'dms' show degrees minutes and seconds
+ *           'dm' show only degrees and minutes
+ *           'd' show only degrees
+ * 
+ * Returns:
+ * {String} the coordinate value formatted as a string
+ */
+OpenLayers.Util.getFormattedLonLat = function(coordinate, axis, dmsOption) {
+    if (!dmsOption) {
+        dmsOption = 'dms';    //default to show degree, minutes, seconds
+    }
+    var abscoordinate = Math.abs(coordinate)
+    var coordinatedegrees = Math.floor(abscoordinate);
+
+    var coordinateminutes = (abscoordinate - coordinatedegrees)/(1/60);
+    var tempcoordinateminutes = coordinateminutes;
+    coordinateminutes = Math.floor(coordinateminutes);
+    var coordinateseconds = (tempcoordinateminutes - coordinateminutes)/(1/60);
+    coordinateseconds =  Math.round(coordinateseconds*10);
+    coordinateseconds /= 10;
+
+    if( coordinatedegrees < 10 ) {
+        coordinatedegrees = "0" + coordinatedegrees;
+    }
+    var str = coordinatedegrees + "\u00B0";
+
+    if (dmsOption.indexOf('dm') >= 0) {
+        if( coordinateminutes < 10 ) {
+            coordinateminutes = "0" + coordinateminutes;
+        }
+        str += coordinateminutes + "'";
+  
+        if (dmsOption.indexOf('dms') >= 0) {
+            if( coordinateseconds < 10 ) {
+                coordinateseconds = "0" + coordinateseconds;
+            }
+            str += coordinateseconds + '"';
+        }
+    }
+    
+    if (axis == "lon") {
+        str += coordinate < 0 ? OpenLayers.i18n("W") : OpenLayers.i18n("E");
+    } else {
+        str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N");
+    }
+    return str;
+};
+

Modified: sandbox/ahocevar/playground/lib/OpenLayers.js
===================================================================
--- sandbox/ahocevar/playground/lib/OpenLayers.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/lib/OpenLayers.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,58 +1,64 @@
-/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
- * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+/* 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/BaseTypes.js
  * @requires OpenLayers/Lang/en.js
  * @requires OpenLayers/Console.js
- */ 
+ */
+ 
+/*
+ * TODO: In 3.0, we will stop supporting build profiles that include
+ * OpenLayers.js. This means we will not need the singleFile and scriptFile
+ * variables, because we don't have to handle the singleFile case any more.
+ */
 
 (function() {
     /**
      * Before creating the OpenLayers namespace, check to see if
      * OpenLayers.singleFile is true.  This occurs if the
      * OpenLayers/SingleFile.js script is included before this one - as is the
-     * case with single file builds.
+     * case with old single file build profiles that included both
+     * OpenLayers.js and OpenLayers/SingleFile.js.
      */
     var singleFile = (typeof OpenLayers == "object" && OpenLayers.singleFile);
     
     /**
+     * Relative path of this script.
+     */
+    var scriptName = (!singleFile) ? "lib/OpenLayers.js" : "OpenLayers.js";
+    
+    /**
      * Namespace: OpenLayers
      * The OpenLayers object provides a namespace for all things OpenLayers
      */
     window.OpenLayers = {
-        
         /**
-         * Property: _scriptName
-         * {String} Relative path of this script.
-         */
-        _scriptName: (!singleFile) ? "lib/OpenLayers.js" : "OpenLayers.js",
-
-        /**
-         * Function: _getScriptLocation
-         * Return the path to this script.
+         * Method: _getScriptLocation
+         * Return the path to this script. This is also implemented in
+         * OpenLayers/SingleFile.js
          *
          * Returns:
          * {String} Path to this script
          */
-        _getScriptLocation: function () {
-            var scriptLocation = "";            
-            var isOL = new RegExp("(^|(.*?\\/))(" + OpenLayers._scriptName + ")(\\?|$)");
-         
-            var scripts = document.getElementsByTagName('script');
-            for (var i=0, len=scripts.length; i<len; i++) {
-                var src = scripts[i].getAttribute('src');
-                if (src) {
-                    var match = src.match(isOL);
-                    if(match) {
-                        scriptLocation = match[1];
+        _getScriptLocation: (function() {
+            var r = new RegExp("(^|(.*?\\/))(" + scriptName + ")(\\?|$)"),
+                s = document.getElementsByTagName('script'),
+                src, m, l = "";
+            for(var i=0, len=s.length; i<len; i++) {
+                src = s[i].getAttribute('src');
+                if(src) {
+                    var m = src.match(r);
+                    if(m) {
+                        l = m[1];
                         break;
                     }
                 }
             }
-            return scriptLocation;
-        }
+            return (function() { return l; });
+        })()
     };
     /**
      * OpenLayers.singleFile is a flag indicating this file is being included
@@ -63,7 +69,7 @@
      * 
      * When we *are* part of a SFL build we do not dynamically include the 
      * OpenLayers library code as it will be appended at the end of this file.
-      */
+     */
     if(!singleFile) {
         var jsfiles = new Array(
             "OpenLayers/Util.js",
@@ -91,12 +97,14 @@
             "OpenLayers/Popup.js",
             "OpenLayers/Tile.js",
             "OpenLayers/Tile/Image.js",
+            "OpenLayers/Tile/Image/IFrame.js",
             "OpenLayers/Tile/WFS.js",
             "OpenLayers/Layer/Image.js",
             "OpenLayers/Layer/SphericalMercator.js",
             "OpenLayers/Layer/EventPane.js",
             "OpenLayers/Layer/FixedZoomLevels.js",
             "OpenLayers/Layer/Google.js",
+            "OpenLayers/Layer/Google/v3.js",
             "OpenLayers/Layer/VirtualEarth.js",
             "OpenLayers/Layer/Yahoo.js",
             "OpenLayers/Layer/HTTPRequest.js",
@@ -113,12 +121,15 @@
             "OpenLayers/Layer/ArcGIS93Rest.js",
             "OpenLayers/Layer/WMS.js",
             "OpenLayers/Layer/WMS/Untiled.js",
+            "OpenLayers/Layer/WMS/Post.js",
+            "OpenLayers/Layer/WMTS.js",
             "OpenLayers/Layer/ArcIMS.js",
             "OpenLayers/Layer/GeoRSS.js",
             "OpenLayers/Layer/Boxes.js",
             "OpenLayers/Layer/XYZ.js",
             "OpenLayers/Layer/TMS.js",
             "OpenLayers/Layer/TileCache.js",
+            "OpenLayers/Layer/Zoomify.js",
             "OpenLayers/Popup/Anchored.js",
             "OpenLayers/Popup/AnchoredBubble.js",
             "OpenLayers/Popup/Framed.js",
@@ -166,6 +177,10 @@
             "OpenLayers/Control/NavigationHistory.js",
             "OpenLayers/Control/Measure.js",
             "OpenLayers/Control/WMSGetFeatureInfo.js",
+            "OpenLayers/Control/WMTSGetFeatureInfo.js",
+            "OpenLayers/Control/Graticule.js",
+            "OpenLayers/Control/TransformFeature.js",
+            "OpenLayers/Control/SLDSelect.js",
             "OpenLayers/Geometry.js",
             "OpenLayers/Geometry/Rectangle.js",
             "OpenLayers/Geometry/Collection.js",
@@ -186,11 +201,18 @@
             "OpenLayers/Layer/Vector.js",
             "OpenLayers/Layer/Vector/RootContainer.js",
             "OpenLayers/Strategy.js",
+            "OpenLayers/Strategy/Filter.js",
             "OpenLayers/Strategy/Fixed.js",
             "OpenLayers/Strategy/Cluster.js",
             "OpenLayers/Strategy/Paging.js",
             "OpenLayers/Strategy/BBOX.js",
             "OpenLayers/Strategy/Save.js",
+            "OpenLayers/Strategy/Refresh.js",
+            "OpenLayers/Filter.js",
+            "OpenLayers/Filter/FeatureId.js",
+            "OpenLayers/Filter/Logical.js",
+            "OpenLayers/Filter/Comparison.js",
+            "OpenLayers/Filter/Spatial.js",
             "OpenLayers/Protocol.js",
             "OpenLayers/Protocol/HTTP.js",
             "OpenLayers/Protocol/SQL.js",
@@ -199,24 +221,24 @@
             "OpenLayers/Protocol/WFS/v1.js",
             "OpenLayers/Protocol/WFS/v1_0_0.js",
             "OpenLayers/Protocol/WFS/v1_1_0.js",
+            "OpenLayers/Protocol/SOS.js",
+            "OpenLayers/Protocol/SOS/v1_0_0.js",
             "OpenLayers/Layer/PointTrack.js",
             "OpenLayers/Layer/GML.js",
             "OpenLayers/Style.js",
+            "OpenLayers/Style2.js",
             "OpenLayers/StyleMap.js",
             "OpenLayers/Rule.js",
-            "OpenLayers/Filter.js",
-            "OpenLayers/Filter/FeatureId.js",
-            "OpenLayers/Filter/Logical.js",
-            "OpenLayers/Filter/Comparison.js",
-            "OpenLayers/Filter/Spatial.js",
             "OpenLayers/Format.js",
             "OpenLayers/Format/XML.js",
+            "OpenLayers/Format/Context.js",
             "OpenLayers/Format/ArcXML.js",
             "OpenLayers/Format/ArcXML/Features.js",
             "OpenLayers/Format/GML.js",
             "OpenLayers/Format/GML/Base.js",
             "OpenLayers/Format/GML/v2.js",
             "OpenLayers/Format/GML/v3.js",
+            "OpenLayers/Format/Atom.js",
             "OpenLayers/Format/KML.js",
             "OpenLayers/Format/GeoRSS.js",
             "OpenLayers/Format/WFS.js",
@@ -237,7 +259,13 @@
             "OpenLayers/Format/SLD.js",
             "OpenLayers/Format/SLD/v1.js",
             "OpenLayers/Format/SLD/v1_0_0.js",
-            "OpenLayers/Format/SLD/v1.js",
+            "OpenLayers/Format/OWSCommon/v1.js",
+            "OpenLayers/Format/OWSCommon/v1_0_0.js",
+            "OpenLayers/Format/OWSCommon/v1_1_0.js",
+            "OpenLayers/Format/CSWGetDomain.js",
+            "OpenLayers/Format/CSWGetDomain/v2_0_2.js",
+            "OpenLayers/Format/CSWGetRecords.js",
+            "OpenLayers/Format/CSWGetRecords/v2_0_2.js",
             "OpenLayers/Format/WFST.js",
             "OpenLayers/Format/WFST/v1.js",
             "OpenLayers/Format/WFST/v1_0_0.js",
@@ -250,10 +278,21 @@
             "OpenLayers/Format/WMC/v1_0_0.js",
             "OpenLayers/Format/WMC/v1_1_0.js",
             "OpenLayers/Format/WMSCapabilities.js",
+            "OpenLayers/Format/WMSCapabilities/v1.js",
             "OpenLayers/Format/WMSCapabilities/v1_1.js",
             "OpenLayers/Format/WMSCapabilities/v1_1_0.js",
             "OpenLayers/Format/WMSCapabilities/v1_1_1.js",
+            "OpenLayers/Format/WMSCapabilities/v1_3.js",
+            "OpenLayers/Format/WMSCapabilities/v1_3_0.js",
             "OpenLayers/Format/WMSGetFeatureInfo.js",
+            "OpenLayers/Format/SOSCapabilities.js",
+            "OpenLayers/Format/SOSCapabilities/v1_0_0.js",
+            "OpenLayers/Format/SOSGetFeatureOfInterest.js",
+            "OpenLayers/Format/SOSGetObservation.js",
+            "OpenLayers/Format/OWSContext.js",
+            "OpenLayers/Format/OWSContext/v0_3_1.js",
+            "OpenLayers/Format/WMTSCapabilities.js",
+            "OpenLayers/Format/WMTSCapabilities/v1_0_0.js",
             "OpenLayers/Layer/WFS.js",
             "OpenLayers/Control/GetFeature.js",
             "OpenLayers/Control/MouseToolbar.js",
@@ -264,6 +303,12 @@
             "OpenLayers/Control/ZoomOut.js",
             "OpenLayers/Control/ZoomPanel.js",
             "OpenLayers/Control/EditingToolbar.js",
+            "OpenLayers/Symbolizer.js",
+            "OpenLayers/Symbolizer/Point.js",
+            "OpenLayers/Symbolizer/Line.js",
+            "OpenLayers/Symbolizer/Polygon.js",
+            "OpenLayers/Symbolizer/Text.js",
+            "OpenLayers/Symbolizer/Raster.js",
             "OpenLayers/Lang.js",
             "OpenLayers/Lang/en.js"
         ); // etc.

Modified: sandbox/ahocevar/playground/license.txt
===================================================================
--- sandbox/ahocevar/playground/license.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/license.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,9 +1,10 @@
 This license applies to all code and content in the 'branches', 'trunk', and
 'project' directories of the Openlayers code repository at svn.openlayers.org,
 and applies to all release of OpenLayers later than 2.5.
+ 
+Copyright (c) 2005-2010 OpenLayers Contributors. See authors.txt for
+  full list.
 
-Copyright (c) 2005-2008 MetaCarta, Inc.
-
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -18,9 +19,9 @@
    documentation and/or other materials provided with the
    distribution.
 
- * Neither the name of MetaCarta, Inc. nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
+ * Neither the name of OpenLayers nor the names of its contributors 
+   may be used to endorse or promote products derived from this 
+   software without specific prior written permission.
 
 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
 GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT

Modified: sandbox/ahocevar/playground/news.txt
===================================================================
--- sandbox/ahocevar/playground/news.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/news.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,13 @@
+OpenLayers 2.9:
+ r10251
+ Released 04/22/10
+ http://trac.openlayers.org/wiki/Release/2.9/Notes
+
+OpenLayers 2.8:
+ r9492
+ Released 06/22/09
+ http://trac.openlayers.org/wiki/Release/2.8/Notes
+
 OpenLayers 2.7:
  r8063
  Released 09/29/08

Modified: sandbox/ahocevar/playground/readme.txt
===================================================================
--- sandbox/ahocevar/playground/readme.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/readme.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,7 +1,9 @@
 OpenLayers
 -=-=-=-=-=-
-Copyright (c) 2005-2008 MetaCarta, Inc.
 
+Copyright (c) 2005-2010 OpenLayers Contributors. See authors.txt for
+more details.
+
 OpenLayers is a JavaScript library for building map applications
 on the web. OpenLayers is made available under a BSD-license.
 Please see license.txt in this distribution for more details.
@@ -29,7 +31,7 @@
 
 As an example, using bash (with the release files in ~/openlayers ):
 $ cd /var/www/html
-$ cp ~/openlayers/build/OpenLayers.js ./
+$ cp ~/openlayers/OpenLayers.js ./
 $ cp -R ~/openlayers/theme ./
 $ cp -R ~/openlayers/img ./
 

Modified: sandbox/ahocevar/playground/release-license.txt
===================================================================
--- sandbox/ahocevar/playground/release-license.txt	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/release-license.txt	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,3 +1,3 @@
 This license information is now available at:
-
+ 
 http://svn.openlayers.org/trunk/openlayers/license.txt

Modified: sandbox/ahocevar/playground/tests/BaseTypes/Element.html
===================================================================
--- sandbox/ahocevar/playground/tests/BaseTypes/Element.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/BaseTypes/Element.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -60,7 +60,7 @@
             }
         };
 
-        OpenLayers.Element.hide(elem1, elem2);
+        OpenLayers.Element.hide(elem1, elem2, "do-not-exists");
         
         t.eq(elem1.style.display, "none", "hidden element stays hidden");
         t.eq(elem2.style.display, "none", "shown element hidden");
@@ -81,7 +81,7 @@
             }
         };
 
-        OpenLayers.Element.show(elem1, elem2);
+        OpenLayers.Element.show(elem1, "do-not-exists", elem2);
         
         t.eq(elem1.style.display, "", "hidden element shown");
         t.eq(elem2.style.display, "", "shown element stays shown");
@@ -110,37 +110,6 @@
         t.ok(OpenLayers.Element.getHeight(elem) == elem.offsetHeight, "offsetHeight returned");
     }
     
-    function test_Element_getDimensions(t) {
-        if (!t.open_window) { 
-            t.plan(0);
-            return;
-        } else {    
-            t.plan(4);
-        }    
-        
-      //shown
-        t.open_window( "BaseTypes/Element.html", function( wnd ) {
-            t.delay_call(1, function() {
-                var elem = wnd.document.getElementById("elemID");
-
-                var dims = OpenLayers.Element.getDimensions(elem);
-                t.eq(dims.width, 50, "width correct when displayed");
-                t.eq(dims.height, 100, "height correct when displayed")
-      
-                elem.style.display = "none";
-                dims = OpenLayers.Element.getDimensions(elem);
-                t.eq(dims.width, 50, "width correct when hidden");
-                t.eq(dims.height, 100, "height correct when hidden")
-      
-
-            });
-        });      
-      
-      //hidden
-        
-
-    }    
-
     function test_hasClass(t) {        
         t.plan(14);
         var has = OpenLayers.Element.hasClass;
@@ -243,7 +212,7 @@
         style = "chickenHead";
         t.ok(OpenLayers.Element.getStyle(elem, style) == null, "get style on 'auto' style returns null");
 
-        if (OpenLayers.Util.getBrowserName() == "opera") {
+        if (OpenLayers.BROWSER_NAME == "opera") {
             elem.style.top = "15px";
             style = "top";
 

Modified: sandbox/ahocevar/playground/tests/BaseTypes/LonLat.html
===================================================================
--- sandbox/ahocevar/playground/tests/BaseTypes/LonLat.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/BaseTypes/LonLat.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -52,7 +52,7 @@
     }
 
     function test_LonLat_add(t) {
-        t.plan( 8 );
+        t.plan(10);
 
         origLL = new OpenLayers.LonLat(10,100);
         lonlatA = origLL.clone();
@@ -76,6 +76,11 @@
         addpx = lonlatA.add(5, null);
         t.ok( lonlatA.equals(origLL), "lonlatA is not modified by erroneous add operation (null lat)");
         t.ok(addpx == null, "returns null on erroneous add operation (null lat)");
+
+        // string values
+        addpx = origLL.clone().add("5", "50");
+        t.eq(addpx.lon, 15, "addpx.lon is set correctly");
+        t.eq(addpx.lat, 150, "addpx.lat is set correctly");
     }
     
     function test_LonLat_equals(t) {

Modified: sandbox/ahocevar/playground/tests/BaseTypes.html
===================================================================
--- sandbox/ahocevar/playground/tests/BaseTypes.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/BaseTypes.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -357,8 +357,160 @@
         
     }
 
+    function test_Date_toISOString(t) {
+        t.plan(3);
+    
+        var date, str;
+
+        // check valid date
+        date = new Date(Date.UTC(2010, 10, 27, 18, 19, 15, 123));
+        str = OpenLayers.Date.toISOString(date);
+        t.eq(str, "2010-11-27T18:19:15.123Z", "valid date");
         
+        // check zero padding
+        date = new Date(Date.UTC(2010, 7, 7, 18, 9, 5, 12));
+        str = OpenLayers.Date.toISOString(date);
+        t.eq(str, "2010-08-07T18:09:05.012Z", "zero padding");
+        
+        // check invalid date
+        date = new Date("foo");
+        str = OpenLayers.Date.toISOString(date);
+        t.eq(str, "Invalid Date", "invalid date");
 
+    }
+    
+    function test_Date_parse(t) {
+        
+        t.plan(93);
+        
+        var cases = {
+            "2000": {
+                year: 2000,
+                month: 0,
+                date: 1
+            },
+            "2005-10": {
+                year: 2005,
+                month: 9,
+                date: 1
+            },
+            "1971-07-23": {
+                year: 1971,
+                month: 6,
+                date: 23
+            },
+            "1801-11-20T04:30:15Z": {
+                year: 1801,
+                month: 10,
+                date: 20,
+                hour: 4,
+                minutes: 30,
+                seconds: 15
+            },
+            "1989-06-15T18:30:15.91Z": {
+                year: 1989,
+                month: 5,
+                date: 15,
+                hour: 18,
+                minutes: 30,
+                seconds: 15,
+                milliseconds: 910
+            },
+            "1989-06-15T18:30:15.091Z": {
+                year: 1989,
+                month: 5,
+                date: 15,
+                hour: 18,
+                minutes: 30,
+                seconds: 15,
+                milliseconds: 91
+            },
+            "1989-06-15T13:30:15.091-05": {
+                year: 1989,
+                month: 5,
+                date: 15,
+                hour: 18,
+                minutes: 30,
+                seconds: 15,
+                milliseconds: 91
+            },
+            "2010-08-06T15:21:25-06": { // MDT
+                year: 2010,
+                month: 7,
+                date: 6,
+                hour: 21,
+                minutes: 21,
+                seconds: 25
+            },
+            "2010-08-07T06:21:25+9": { // JSP
+                year: 2010,
+                month: 7,
+                date: 6,
+                hour: 21,
+                minutes: 21,
+                seconds: 25
+            },
+            "2010-08-07T02:51:25+05:30": { // IST
+                year: 2010,
+                month: 7,
+                date: 6,
+                hour: 21,
+                minutes: 21,
+                seconds: 25
+            },
+            "T21:51:25Z": {
+                hour: 21,
+                minutes: 51,
+                seconds: 25
+            },
+            "T02:51:25+05:30": { // IST
+                hour: 21,
+                minutes: 21,
+                seconds: 25
+            },
+            "T2:51:25.1234-7": { // lenient
+                hour: 9,
+                minutes: 51,
+                seconds: 25,
+                milliseconds: 123
+            }
+        };
+
+        var o, got, exp;
+        for (var str in cases) {
+            o = cases[str];
+            got = OpenLayers.Date.parse(str);
+            exp = new Date(Date.UTC(o.year || 0, o.month || 0, o.date || 1, o.hour || 0, o.minutes || 0, o.seconds || 0, o.milliseconds || 0));
+            if ("year" in o) {
+                t.eq(got.getUTCFullYear(), exp.getUTCFullYear(), str + ": correct UTCFullYear");
+                t.eq(got.getUTCMonth(), exp.getUTCMonth(), str + ": correct UTCMonth");
+                t.eq(got.getUTCDate(), exp.getUTCDate(), str + ": correct UTCDate");
+            } else {
+                t.ok(true, str + ": ECMA doesn't specify how years are handled in time only strings");
+                t.ok(true, str + ": ECMA doesn't specify how months are handled in time only strings");
+                t.ok(true, str + ": ECMA doesn't specify how days are handled in time only strings");
+            }
+            if ("hour" in o) {
+                t.eq(got.getUTCHours(), exp.getUTCHours(), str + ": correct UTCHours");
+                t.eq(got.getUTCMinutes(), exp.getUTCMinutes(), str + ": correct UTCMinutes");
+                t.eq(got.getUTCSeconds(), exp.getUTCSeconds(), str + ": correct UTCSeconds");
+                t.eq(got.getUTCMilliseconds(), exp.getUTCMilliseconds(), str + ": correct UTCMilliseconds");
+            } else {
+                t.ok(true, str + ": ECMA doesn't specify how hours are handled in date only strings");
+                t.ok(true, str + ": ECMA doesn't specify how minutes are handled in date only strings");
+                t.ok(true, str + ": ECMA doesn't specify how seconds are handled in date only strings");
+                t.ok(true, str + ": ECMA doesn't specify how milliseconds are handled in date only strings");
+            }
+        }
+        
+        // check invalid date parsing
+        var invalid = OpenLayers.Date.parse("foo");
+        t.ok(invalid instanceof Date, "invalid is a date");
+        t.ok(isNaN(invalid.getTime()), "invalid has no time");
+            
+
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/Attribution.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/Attribution.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/Attribution.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -35,6 +35,22 @@
 
 
     }    
+    
+    function test_Control_Attribution_no_duplicates(t) {
+        t.plan(2);
+        
+        map = new OpenLayers.Map("map");
+        map.addLayer(new OpenLayers.Layer("Company A: 1",{'attribution':'company A'}));
+        map.addLayer(new OpenLayers.Layer("Company A: 2",{'attribution':'company A'}));
+
+        control = new OpenLayers.Control.Attribution();
+        map.addControl(control);
+        t.eq(control.div.innerHTML, 'company A', "Attribution not duplicated.");
+                
+        map.addLayer(new OpenLayers.Layer("Company B: 1",{'attribution':'company B'}));
+        map.addLayer(new OpenLayers.Layer("Company A: 3",{'attribution':'company A'}));
+        t.eq(control.div.innerHTML, 'company A, company B', "Attribution correct with four layers (3 with same attribution).");
+    }
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/DragPan.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/DragPan.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/DragPan.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -36,6 +36,28 @@
         t.eq(map.getCenter().lat, res * 5, "Lat is " + (res * 5) + " after drag");
         t.eq(map.getCenter().lon, res * -5, "Lon is " + (res * -5) + " after drag");
     }
+    function test_Control_DragPan_drag_documentDrag (t) {
+        t.plan(4);
+        control = new OpenLayers.Control.DragPan({documentDrag: true});
+        map = new OpenLayers.Map("map", {controls:[control]});
+        layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://labs.metacarta.com/wms/vmap0",
+                    {layers: 'basic'} );
+        map.addLayer(layer);
+        map.zoomToMaxExtent();
+        map.zoomIn();
+        control.activate();
+
+        res = map.baseLayer.resolutions[map.getZoom()];
+        t.eq(map.center.lat, 0, "Lat is 0 before drag");
+        t.eq(map.center.lon, 0, "Lon is 0 before drag");
+        map.events.triggerEvent('mousedown', {'type':'mousedown', 'xy':new OpenLayers.Pixel(0,0), 'which':1});
+        map.events.triggerEvent('mousemove', {'type':'mousemove', 'xy':new OpenLayers.Pixel(5,5), 'which':1});
+        map.events.triggerEvent('mouseup', {'type':'mouseup', 'xy':new OpenLayers.Pixel(5,5), 'which':1});
+        
+        t.eq(map.getCenter().lat, res * 5, "Lat is " + (res * 5) + " after drag");
+        t.eq(map.getCenter().lon, res * -5, "Lon is " + (res * -5) + " after drag");
+    }
     function test_Control_DragPan_click(t) {
         t.plan(1);
         var control = new OpenLayers.Control.DragPan();

Modified: sandbox/ahocevar/playground/tests/Control/DrawFeature.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/DrawFeature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/DrawFeature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,6 +12,34 @@
              "featureadded event in EVENT_TYPES");
     }
     
+    function test_multi(t) {
+        t.plan(4);
+
+        var layer = new OpenLayers.Layer.Vector();
+        var control;
+        
+        // multi false by default
+        control = new OpenLayers.Control.DrawFeature(
+            layer, OpenLayers.Handler.Polygon
+        );
+        t.ok(!control.multi, "control.multi false by default");
+        t.ok(!control.handler.multi, "handler.multi false by default");
+        
+        // set on handler
+        control = new OpenLayers.Control.DrawFeature(
+            layer, OpenLayers.Handler.Polygon, {multi: true}
+        );
+        t.ok(control.handler.multi, "handler.multi set from control options");
+        
+        // respect handlerOptions
+        control = new OpenLayers.Control.DrawFeature(
+            layer, OpenLayers.Handler.Polygon,
+            {multi: true, handlerOptions: {multi: false}}
+        );
+        t.ok(!control.handler.multi, "handlerOptions.multi respected");
+
+    }
+    
     function test_drawFeature(t) {
         t.plan(3);
         var layer = new OpenLayers.Layer.Vector();

Modified: sandbox/ahocevar/playground/tests/Control/GetFeature.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/GetFeature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/GetFeature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -3,7 +3,7 @@
     <script src="../../lib/OpenLayers.js"></script>
     <script type="text/javascript">
     function test_Control_GetFeature_constructor(t) {
-        t.plan(2);
+        t.plan(3);
         var protocol = "foo";
         var control = new OpenLayers.Control.GetFeature({
             protocol: protocol
@@ -12,10 +12,18 @@
              "new OpenLayers.Control.SelectFeature returns an instance");
         t.eq(control.protocol, "foo",
              "constructor sets protocol correctly");        
+
+        control = new OpenLayers.Control.GetFeature({
+            filterType: OpenLayers.Filter.Spatial.INTERSECTS
+        });
+        t.eq(control.filterType, OpenLayers.Filter.Spatial.INTERSECTS,
+             "constructor sets filterType correctly");        
+
     }
     
     function test_Control_GetFeature_select(t) {
-        t.plan(3);
+        t.plan(10);
+        var cssAdded;
         var map = new OpenLayers.Map("map");
         var layer = new OpenLayers.Layer.WMS("foo", "wms", {
             layers: "foo"
@@ -24,12 +32,15 @@
         map.setCenter(new OpenLayers.LonLat(1,2));
         var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2));
         var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(2,3));
+        var feature3 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(3,1));
         var control = new OpenLayers.Control.GetFeature({
             protocol: new OpenLayers.Protocol({
                 read: function(obj) {
+                    cssAdded = OpenLayers.Element.hasClass(map.viewPortDiv,
+                                                           "olCursorWait");
                     obj.callback.call(obj.scope, {
-                        features: [feature1, feature2],
-                        code: 1
+                        features: [feature1, feature2, feature3],
+                        success: function() {return true;}
                     });
                 }
             }),
@@ -40,23 +51,60 @@
         var singleTest = function(evt) {
             t.eq(evt.feature.id, feature1.id, "featureselected callback called with closest feature");
         }
+        cssAdded = false;
         control.events.register("featureselected", this, singleTest);
-        control.selectSingle({xy: new OpenLayers.Pixel(200, 125)});
+        control.selectClick({xy: new OpenLayers.Pixel(200, 125)});
+        t.ok(cssAdded,
+             "select adds CSS class (click)");
+        t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"),
+             "callback removes CSS class (click)");
         control.events.unregister("featureselected", this, singleTest);
-        
-        var features = []
+
+        var count = 0;
+        var beforeFeatureSelected = function(evt) {
+             count++;
+             return count < 3;
+        }
+        var features = [];
         var boxTest = function(evt) {
             features.push(evt.feature);
         }
+        var beforeFeaturesSelected = function(evt) {
+            t.eq(evt.features.length, 3, "3 features passed to the beforefeaturesselected handler");
+        }
+        var featuresSelected = function(evt) {
+            t.eq(evt.features.length, 2, "2 features passed to the featuresselected handler");
+        }
+        control.events.register("beforefeatureselected", this, beforeFeatureSelected);
         control.events.register("featureselected", this, boxTest);
+        control.events.register("beforefeaturesselected", this, beforeFeaturesSelected);
+        control.events.register("featuresselected", this, featuresSelected);
+        cssAdded = false;
         control.selectBox(new OpenLayers.Bounds(0,0,4,4));
+        control.events.unregister("beforefeatureselected", this, beforeFeatureSelected);
         control.events.unregister("featureselected", this, boxTest);
+        control.events.unregister("beforefeaturesselected", this, beforeFeaturesSelected);
+        control.events.unregister("featuresselected", this, featuresSelected);
         t.eq(features.length, 2, "2 features inside box selected");
         t.eq(features[1].id, feature2.id, "featureselected callback called with multiple features");
+        t.ok(cssAdded,
+             "select adds CSS class (box)");
+        t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"),
+             "callback removes CSS class (box)");
+
+        // allow several features even for single click 
+        control.single = false;
+        var multiplePointTest = function(evt) {
+            t.eq(evt.features.length, 3, "3 features passed to the featuresselected handler");
+        }
+        control.events.register("featuresselected", this, multiplePointTest);
+        control.selectClick({xy: new OpenLayers.Pixel(200, 125)});
+        control.events.unregister("featuresselected", this, multiplePointTest);
     }
     
     function test_Control_GetFeature_hover(t) {
-        t.plan(6);
+        t.plan(9);
+        var cssAdded;
         var abortedResponse = null;
         var map = new OpenLayers.Map("map");
         var layer = new OpenLayers.Layer.WMS("foo", "wms", {
@@ -70,9 +118,11 @@
         var control = new OpenLayers.Control.GetFeature({
             protocol: new OpenLayers.Protocol({
                 read: function(obj){
+                    cssAdded = OpenLayers.Element.hasClass(map.viewPortDiv,
+                                                           "olCursorWait");
                     obj.callback.call(obj.scope, {
                         features: [feature1, feature2],
-                        code: 1
+                        success: function() {return true;}
                     });
                     return response;
                 },
@@ -99,12 +149,21 @@
              "selectHover stores the protocol response in the hoverResponse property");
 
         hoverFeature = feature2;
+        cssAdded = false;
         control.selectHover({xy: new OpenLayers.Pixel(400, 0)});
+        t.ok(cssAdded,
+             "select adds CSS class (hover)");
+        t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"),
+             "callback removes CSS class (hover)");
+
+        OpenLayers.Element.addClass(map.viewPortDiv, "olCursorWait");
         control.cancelHover();
         t.ok(abortedResponse == response,
              "cancelHover calls protocol.abort() with the expected response");
         t.eq(control.hoverResponse, null,
              "cancelHover sets this.hoverResponse to null");
+        t.ok(!OpenLayers.Element.hasClass(map.viewPortDiv, "olCursorWait"),
+             "cancelHover removes CSS class");
 
         control.events.unregister("hoverfeature", this, hoverTest);
         control.events.unregister("outfeature", this, outTest);

Copied: sandbox/ahocevar/playground/tests/Control/Graticule.html (from rev 10919, trunk/openlayers/tests/Control/Graticule.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Control/Graticule.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Control/Graticule.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,66 @@
+<html>
+<head>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script src="http://proj4js.org/lib/proj4js-compressed.js"></script>
+    <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(2);
+        var options = {};
+        var map = new OpenLayers.Map("map",{projection:"EPSG:4326"});
+        var layer = new OpenLayers.Layer.WMS();
+        map.addLayers([layer]);
+
+        var control = new OpenLayers.Control.Graticule(options);
+        map.addControl(control);
+        map.zoomToMaxExtent();
+
+        t.ok(control.gratLayer instanceof OpenLayers.Layer.Vector,
+             "constructor sets layer correctly");
+        t.ok(control.gratLayer.features.length > 0,
+             "graticule has features");
+        control.destroy();
+    }
+    
+    function test_activate(t) {        
+        t.plan(7);
+        var map = new OpenLayers.Map("map",{projection:"EPSG:4326"});
+        var layer = new OpenLayers.Layer.WMS();
+        map.addLayers([layer]);
+
+        var control = new OpenLayers.Control.Graticule({});
+        map.addControl(control);
+        map.zoomToMaxExtent();
+        
+        t.ok(control.gratLayer.visibility, "Graticule layer is visible by default"); 
+        control.deactivate();
+        t.ok(control.gratLayer.map == null, 
+            "Graticule layer is not in map when control is deactivated"); 
+        control.destroy();
+        
+        var control2 = new OpenLayers.Control.Graticule({autoActivate:false});
+        map.addControl(control2);
+        t.ok(control2.gratLayer.map == null, 
+            "Graticule layer is not in map when autoActivate:false"); 
+        t.ok(control2.gratLayer.features.length == 0, 
+            "Graticule layer is empty when autoActivate:false");
+        control2.activate();
+        t.ok(control2.gratLayer.map != null, 
+            "Graticule layer is on map when control is activated");    
+        t.ok(control2.gratLayer.features.length > 0,
+            "Graticule features refreshed after control is activated");
+        control2.gratLayer.setVisibility(false);
+       
+        control2.destroy();
+        t.ok(control2.gratLayer == null, 
+            "Graticule layer is destroyed when control is destroyed");    
+            
+        map.destroy();        
+    }
+
+    </script>
+</head>
+<body>
+    <div id="map" style="width: 400px; height: 250px;"/>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Control/LayerSwitcher.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/LayerSwitcher.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/LayerSwitcher.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -32,12 +32,12 @@
         t.eq(control.div.style.width, "250px", "Div is not minimized when added."); 
         control = new OpenLayers.Control.LayerSwitcher();
         map.addControl(control);
-        t.eq(control.div.style.width, "0px", "Div is minimized when added."); 
+        t.eq(control.div.style.width, "0px", "Div is minimized when added.");
     }
  
     function test_Control_LayerSwitcher_loadContents(t) {
 
-        t.plan( 5 );
+        t.plan( 10 );
 
         map = new OpenLayers.Map('map');
         var layer = new OpenLayers.Layer.WMS("WMS", 
@@ -52,20 +52,26 @@
         map.addControl(control);
 
         t.ok(control.layersDiv != null, "correctly makes layers div");
+        t.ok(OpenLayers.Element.hasClass(control.layersDiv, "layersDiv"),
+             "layers div has class layersDiv");
         t.ok(control.baseLayersDiv != null, "correctly makes layers div");
+        t.ok(OpenLayers.Element.hasClass(control.baseLayersDiv, "baseLayersDiv"),
+             "base layers div has class baseLayersDiv");
         t.ok(control.dataLayersDiv != null, "correctly makes layers div");
-
+        t.ok(OpenLayers.Element.hasClass(control.dataLayersDiv, "dataLayersDiv"),
+             "data layers div has class dataLayersDiv");
         t.ok(control.maximizeDiv != null, "correctly makes resize div");
+        t.ok(OpenLayers.Element.hasClass(control.maximizeDiv, "maximizeDiv"),
+             "maximize div has class maximizeDiv");
         t.ok(control.minimizeDiv != null, "correctly makes resize div");
-
-        
-
+        t.ok(OpenLayers.Element.hasClass(control.minimizeDiv, "minimizeDiv"),
+             "minimize div has class minmizeDiv");
     }
 
 
     function test_Control_LayerSwitcher_redraw (t) {
 
-        t.plan( (OpenLayers.Util.getBrowserName() == "opera" ? 9 : 19 ) );
+        t.plan( (OpenLayers.BROWSER_NAME == "opera" ? 9 : 19 ) );
 
         map = new OpenLayers.Map('map');
         var layer = new OpenLayers.Layer.WMS("WMS", 
@@ -82,7 +88,7 @@
         var wmsInput = OpenLayers.Util.getElement(control.id + "_input_" + layer.name);
         t.ok(wmsInput != null, "correctly makes an input for wms layer");
         t.eq(wmsInput.type, "radio", "wms correctly made a radio button");
-        t.eq(wmsInput.name, "baseLayers", "wms correctly named");
+        t.eq(wmsInput.name, control.id + "_baseLayers", "wms correctly named");
         t.eq(wmsInput.value, layer.name, "wms correctly valued");
         
         var markersInput = OpenLayers.Util.getElement(control.id + "_input_" + markers.name);
@@ -92,14 +98,14 @@
         t.eq(markersInput.value, markers.name, "wms correctly valued");
 
         t.eq(false, control.checkRedraw(), "check redraw is false");
-        if (OpenLayers.Util.getBrowserName() != "opera") { 
+        if (OpenLayers.BROWSER_NAME != "opera") { 
             control = new OpenLayers.Control.LayerSwitcher();
             var myredraw = control.redraw;
             control.redraw = function() { 
                 t.ok(true, "redraw called when setting vis");
             }
             map.addControl(control); 
-            var func = myredraw.bind(control);
+            var func = OpenLayers.Function.bind(myredraw, control);
             func();
             markers.setVisibility(false); 
             t.eq(control.checkRedraw(), true, "check redraw is true after changing layer and not letting redraw happen.");
@@ -111,7 +117,7 @@
                 t.ok(true, "redraw called when setting inRange");
             }
             map.addControl(control); 
-            var func = myredraw.bind(control);
+            var func = OpenLayers.Function.bind(myredraw, control);
             func();
             markers.inRange = false;
             t.eq(control.checkRedraw(), true, "check redraw is true after changing layer.inRange and not letting redraw happen.");
@@ -124,7 +130,7 @@
             }
             
             map.addControl(control); 
-            var func = myredraw.bind(control);
+            var func = OpenLayers.Function.bind(myredraw, control);
             func();
             map.raiseLayer(layer, 1);
             t.eq(control.checkRedraw(), true, "check redraw is true after changing layer.inRange and not letting redraw happen.");

Modified: sandbox/ahocevar/playground/tests/Control/Measure.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/Measure.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/Measure.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -19,6 +19,7 @@
         
     }
     
+    // test for <http://trac.openlayers.org/ticket/2691>
     function test_cancel(t) {
         
         t.plan(4);
@@ -67,6 +68,297 @@
         
     }
 
+    function test_partial(t) {        
+
+        t.plan(28);        
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            units: "m",
+            resolutions: [1],
+            layers: [
+                new OpenLayers.Layer(null, {
+                    isBaseLayer: true
+                })
+            ],
+            center: new OpenLayers.LonLat(0, 0)
+        });
+
+        var log = [];
+        var control = new OpenLayers.Control.Measure(
+            OpenLayers.Handler.Path, {persist: true, 
+                eventListeners: {
+                    measurepartial: function(evt) {
+                        log.push(evt);
+                    },
+                    measure: function(evt){
+                        log.push(evt);
+                    }
+                }
+            }
+        );
+        map.addControl(control);
+        control.activate();
+        
+        
+        // convenience function to trigger mouse events
+        function trigger(type, x, y) {
+            map.events.triggerEvent(type, {
+                xy: new OpenLayers.Pixel(x, y)
+            })
+        };
+        
+        // delay in seconds
+        var delay = control.partialDelay / 1000;
+        
+        // establish first point
+        trigger("mousedown", 0, 0);
+        trigger("mouseup", 0, 0);
+
+        
+        // a) move 10 pixels and click
+        trigger("mousemove", 0, 10);
+        trigger("mousedown", 0, 10);
+        trigger("mouseup", 0, 10);
+        
+        // confirm measurepartial is not fired before delay
+        t.eq(log.length, 0, "a) no event fired yet")
+
+        t.delay_call( 
+            // wait for delay then confirm event was logged
+            delay, function() {
+                t.eq(log.length, 1, "a) event logged")
+                t.eq(log[0].type, "measurepartial", "a) event logged");
+                t.eq(log[0].measure, 10, "a) correct measure");
+                
+                // b) move 10 pixels and click
+                trigger("mousemove", 0, 20);
+                trigger("mousedown", 0, 20);
+                trigger("mouseup", 0, 20);
+                
+                // confirm measurepartial is not fired before delay
+                t.eq(log.length, 1, "b) no event fired yet")
+                
+            },
+            delay, function() {
+                t.eq(log.length, 2, "b) event logged");
+                t.eq(log[1].type, "measurepartial", "b) correct type");
+                t.eq(log[1].measure, 20, "b) correct measure");
+
+                // c) move 10 pixels and click
+                trigger("mousemove", 0, 30);
+                trigger("mousedown", 0, 30);
+                trigger("mouseup", 0, 30);
+            },
+            // wait for half delay and confirm event not logged
+            delay / 2, function() {
+                // confirm measurepartial is not fired before delay
+                t.eq(log.length, 2, "c) no event fired yet")
+            },
+            // wait for rest of delay and confirm event logged
+            delay / 2, function() {
+                t.eq(log.length, 3, "c) event logged");
+                t.eq(log[2].type, "measurepartial", "c) correct type");
+                t.eq(log[2].measure, 30, "c) correct measure");
+                
+                // d) move 10 pixels and click
+                trigger("mousemove", 0, 40);
+                trigger("mousedown", 0, 40);
+                trigger("mouseup", 0, 40);
+
+                // confirm measurepartial is not fired before delay
+                t.eq(log.length, 3, "d) no event fired yet")
+                
+                // e) double click to finish
+                trigger("dblclick", 0, 40);
+
+                t.eq(log.length, 4, "e) event logged");
+                t.eq(log[3].type, "measure", "e) correct type");
+                t.eq(log[3].measure, 40, "e) correct measure");                
+            },
+            // wait for rest of delay and confirm no measurepartial logged
+            delay, function() {
+                // confirm measurepartial is not fired after dblclick
+                t.eq(log.length, 4, "e) no additional event fired");
+                
+                // change to freehand mode and confirm synchronous event dispatch
+                control.handler.freehand = true;
+                // clear log
+                log = [];
+                
+                // f) establish first freehand point
+                trigger("mousedown", 0, 0);
+                t.eq(log.length, 0, "f) no event fired yet")
+                
+                // g) move 10 pixels
+                trigger("mousemove", 10, 0);
+
+                t.eq(log.length, 1, "g) event logged");
+                t.eq(log[0].type, "measurepartial", "g) correct type");
+                t.eq(log[0].measure, 10, "g) correct measure");
+                
+                // h) move 10 pixels
+                trigger("mousemove", 20, 0);
+
+                t.eq(log.length, 2, "h) event logged");
+                t.eq(log[1].type, "measurepartial", "h) correct type");
+                t.eq(log[1].measure, 20, "h) correct measure");
+                
+                // i) mouse up to finish
+                trigger("mouseup", 20, 0);
+
+                t.eq(log.length, 3, "i) event logged");
+                t.eq(log[2].type, "measure", "i) correct type");
+                t.eq(log[2].measure, 20, "i) correct measure");
+                
+                // j) clean up
+                log = [];
+                map.destroy();
+            },
+            // wait for delay and confirm event not logged
+            delay, function() {
+                t.eq(log.length, 0, "j) no event fired after destroy");
+            }
+        );
+        
+    }
+
+    function test_immediate(t) {
+        t.plan(29);
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            units: "m",
+            resolutions: [1],
+            layers: [
+                new OpenLayers.Layer(null, {
+                    isBaseLayer: true
+                })
+            ],
+            center: new OpenLayers.LonLat(0, 0)
+        });
+        
+        var log = [];
+        var control = new OpenLayers.Control.Measure(
+            OpenLayers.Handler.Path, {
+                persist: true,
+                immediate: true,
+                eventListeners: {
+                    measurepartial: function(evt) {
+                        log.push(evt);
+                    },
+                    measure: function(evt){
+                        log.push(evt);
+                    }
+                }
+            }
+        );
+        map.addControl(control);
+        control.activate();
+        
+        // convenience function to trigger mouse events
+        function trigger(type, x, y) {
+            map.events.triggerEvent(type, {
+                xy: new OpenLayers.Pixel(x, y)
+            })
+        };
+
+        // delay in seconds
+        var delay = control.partialDelay / 1000;
+
+        // a) establish first point
+        trigger("mousedown", 0, 0);
+        trigger("mouseup", 0, 0);
+
+        // move 10 pixels
+        trigger("mousemove", 0, 10);
+
+        t.eq(log.length, 0, "a) no event fired yet");
+        
+        t.delay_call(
+            delay, function() {
+                // confirm measurepartial is fired
+                t.eq(log.length, 1, "a) event logged");
+                t.eq(log[0].type, "measurepartial", "a) correct type");
+                // mousemove within the partialDelay fires no event, so the
+                // measure below is the one of the initial point
+                t.eq(log[0].measure, 0, "a) correct measure");
+
+                // b) move 10 pixels
+                trigger("mousemove", 0, 20);
+                // c) move 10 pixels again
+                trigger("mousemove", 0, 30);
+
+                // confirm measurepartial is fired 2 times
+                t.eq(log.length, 3, "b) event logged");
+                t.eq(log[1].type, "measurepartial", "b) correct type");
+                t.eq(log[1].measure, 20, "b) correct measure");
+                t.eq(log[2].type, "measurepartial", "c) correct type");
+                t.eq(log[2].measure, 30, "c) correct measure");
+
+                // d) switch immediate measurement off
+                control.setImmediate(false);
+                t.eq(control.immediate, false, "d) immediate is false");
+
+                // e) move 10 pixels and click
+                trigger("mousemove", 0, 40);
+                trigger("mousedown", 0, 40);
+                trigger("mouseup", 0, 40);
+                // confirm measurepartial is not fired before delay
+                t.eq(log.length, 3, "e) no event fired yet")
+            },
+            // wait for delay then confirm event was logged
+            delay, function() {
+                t.eq(log.length, 4, "e) event logged")
+                t.eq(log[3].type, "measurepartial", "e) correct type");
+                t.eq(log[3].measure, 40, "e) correct measure");
+
+                // f) switch immediate measurement on
+                control.setImmediate(true);
+                t.eq(control.immediate, true, "f) immediate is true");
+
+                // g) move 10 pixels
+                trigger("mousemove", 0, 50);
+            },
+            delay, function() {
+                t.eq(log.length, 5, "g) event logged");
+                t.eq(log[4].type, "measurepartial", "g) correct type");
+                t.eq(log[4].measure, 50, "g) correct measure");
+
+                // h) move 10 pixels
+                trigger("mousemove", 0, 60);
+
+                t.eq(log.length, 6, "h) event logged");
+                t.eq(log[5].type, "measurepartial", "h) correct type");
+                t.eq(log[5].measure, 60, "h) correct measure");
+
+                // i) double click to finish
+                trigger("mousedown", 0, 60);
+                trigger("mouseup", 0, 60);
+                t.eq(log.length, 6, "i) no event fired yet");
+            },
+            delay, function() {
+                t.eq(log.length, 7, "i) event logged");
+                t.eq(log[6].type, "measurepartial", "i) correct type");
+                t.eq(log[6].measure, 60, "i) correct measure");
+                
+                trigger("dblclick", 0, 60);
+                t.eq(log.length, 8, "i) event logged");
+                t.eq(log[7].type, "measure", "i) correct type");
+                t.eq(log[7].measure, 60, "i) correct measure");
+                // clear log
+                log = [];
+
+                // j) clean up
+                map.destroy();
+                // wait for delay and confirm event not logged
+            },
+            delay, function() {
+                t.eq(log.length, 0, "j) no event fired after destroy");
+            }
+        );
+    }
+    
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/ModifyFeature.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/ModifyFeature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/ModifyFeature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -609,6 +609,94 @@
 
         map.destroy();
     }
+    
+    function test_standalone(t) {
+        
+        t.plan(17);
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector();
+        
+        var f1 = new OpenLayers.Feature.Vector(
+            OpenLayers.Geometry.fromWKT("LINESTRING(3 4,10 50,20 25)")
+        );
+        var f2 = new OpenLayers.Feature.Vector(
+            OpenLayers.Geometry.fromWKT("POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2, 3 2, 3 3, 2 3,2 2))")
+        );
+        var f3 = new OpenLayers.Feature.Vector(
+            OpenLayers.Geometry.fromWKT("POINT(10 15)")
+        );
+        var f4 = new OpenLayers.Feature.Vector(
+            OpenLayers.Geometry.fromWKT("POINT(15 10)")
+        );
+        layer.addFeatures([f1, f2, f3, f4]);
+        
+        map.addLayer(layer);
+        var control = new OpenLayers.Control.ModifyFeature(layer, {standalone: true});
+        map.addControl(control);
+        
+        var log = [];
+        layer.events.on({
+            beforefeaturemodified: function(evt) {
+                log.push(evt);
+            },
+            featuremodified: function(evt) {
+                log.push(evt);
+            },
+            afterfeaturemodified: function(evt) {
+                log.push(evt);
+            }
+        });
+        
+        // activate control
+        control.activate();
+        t.eq(control.active, true, "[activate] control activated");
+        t.eq(control.selectControl, null, "[activate] no select control");
+        
+        // manually select feature for editing
+        control.selectFeature(f1);
+        t.ok(control.feature === f1, "[select f1] control.feature set to f1");
+        
+        // manually unselect feature for editing
+        control.unselectFeature(f1);
+        t.eq(control.feature, null, "[unselect f1] control.feature set to null");
+        t.eq(log.length, 1, "[unselect f1] event logged");
+        t.eq(log[0].type, "afterfeaturemodified", "[unselect f1] afterfeaturemodified triggered");
+        t.ok(log[0].feature === f1, "[unselect f1] correct feature");
+        t.eq(log[0].modified, false, "[unselect f1] feature not actually modified");
+        
+        // clear log and select new feature for editing
+        log = [];
+        control.selectFeature(f2);
+        t.ok(control.feature === f2, "[select f2] control.feature set to f2");
+                
+        // deactivate control and confirm feature is unselected
+        control.deactivate();
+        t.eq(log.length, 1, "[deactivate] event logged");
+        t.eq(log[0].type, "afterfeaturemodified", "[deactivate] afterfeaturemodified triggered");
+        t.ok(log[0].feature === f2, "[deactivate] correct feature");
+        t.eq(log[0].modified, false, "[deactivate] feature not actually modified");
+        
+        // reactivate control and select a point feature to see if we can drag
+        // another point feature;
+        control.activate();
+        control.selectFeature(f3);
+        control.dragControl.handlers.feature.triggerCallback("mousemove", "in", [f4]);
+        t.eq(control.dragControl.handlers.drag.active, false, "cannot drag unselected feature f4");
+        control.dragControl.handlers.feature.triggerCallback("mousemove", "in", [f3]);
+        t.eq(control.dragControl.handlers.drag.active, true, "can drag selected feature f3");
+        
+        // select the polygon feature to make sure that we can drag vertices and
+        // virtual vertices
+        control.selectFeature(f2);
+        control.dragControl.handlers.feature.triggerCallback("mousemove", "in", [control.vertices[0]]);
+        t.eq(control.dragControl.handlers.drag.active, true, "can drag vertex of feature f2");
+        control.dragControl.handlers.feature.triggerCallback("mousemove", "in", [control.virtualVertices[0]]);
+        t.eq(control.dragControl.handlers.drag.active, true, "can drag virtual vertex of feature f2");
+        control.deactivate();
+        
+        map.destroy();
+        
+    }
 
 
 

Modified: sandbox/ahocevar/playground/tests/Control/MousePosition.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/MousePosition.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/MousePosition.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -10,21 +10,6 @@
         t.ok( control instanceof OpenLayers.Control.MousePosition, "new OpenLayers.Control returns object" );
         t.eq( control.displayClass,  "olControlMousePosition", "displayClass is correct" );
     }
-    function test_redraw_noLayer_displayProjection(t) {
-        t.plan(2);
-        control = new OpenLayers.Control.MousePosition({'displayProjection': new OpenLayers.Projection("WGS84")});
-        map = new OpenLayers.Map('map');
-        map.addControl(control);
-        control.redraw({'xy': new OpenLayers.Pixel(10,10)});
-        control.redraw({'xy': new OpenLayers.Pixel(12,12)});
-        t.eq(control.div.innerHTML, "", "innerHTML set correctly");
-        l = new OpenLayers.Layer('name', {'isBaseLayer': true});
-        map.addLayer(l);
-        map.zoomToMaxExtent();
-        control.redraw({'xy': new OpenLayers.Pixel(10,10)});
-        control.redraw({'xy': new OpenLayers.Pixel(12,12)});
-        t.eq(control.div.innerHTML, "-175.78125, 85.78125", "innerHTML set correctly when triggered.");
-    }
     function test_destroy(t) {
         t.plan(1);
     
@@ -52,14 +37,17 @@
         map.destroy();     
     }
     function test_redraw_noLayer_displayProjection(t) {
-        t.plan(3);
-        var control = new OpenLayers.Control.MousePosition();
+        t.plan(4);
+        var control = new OpenLayers.Control.MousePosition({'emptyString':''});
         var map = new OpenLayers.Map('map');
         map.addControl(control);
-        t.eq(control.div.innerHTML, "0.00000, 0.00000", "innerHTML set correctly");
+        var control2 = new OpenLayers.Control.MousePosition();
+        map.addControl(control2);
+        t.eq(control2.emptyString, null, "Emptystring is null");
+        t.eq(control.div.innerHTML, "", "innerHTML set correctly");
         control.redraw({'xy': new OpenLayers.Pixel(10,10)});
         control.redraw({'xy': new OpenLayers.Pixel(12,12)});
-        t.eq(control.div.innerHTML, "0.00000, 0.00000", "innerHTML set correctly");
+        t.eq(control.div.innerHTML, "", "innerHTML set correctly");
         var l = new OpenLayers.Layer('name', {'isBaseLayer': true});
         map.addLayer(l);
         map.zoomToMaxExtent();
@@ -80,6 +68,39 @@
         var val = control.formatOutput(lonlat);
         t.eq(val, 'prefix0.757separator0.374suffix', 'formatOutput correctly formats the mouse position output');
     }
+    function test_deactivate(t) {
+        t.plan(4);         
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer(null, {isBaseLayer: true});
+        map.addLayer(layer);
+        map.zoomToMaxExtent();
+        // Auxiliary function
+        function trigger(type, x, y) {
+            map.events.triggerEvent(type, {
+                xy: new OpenLayers.Pixel(x, y)
+            })
+        };        
+
+        var control = new OpenLayers.Control.MousePosition();
+        map.addControl(control);
+        trigger("mousemove", 0, 0);
+
+        trigger("mousemove", 0, 1);
+        t.ok(control.div.innerHTML != "", 
+            "Shows the position after add control (with autoActivate) and move");
+        control.deactivate();
+        t.ok(control.div.innerHTML == "", 
+            "Position is not displayed after deactivate and move");        
+        trigger("mousemove", 0, 2);
+        t.ok(control.div.innerHTML == "", 
+            "Position is not displayed after move when deactivate");
+        control.activate();
+        trigger("mousemove", 0, 3);
+        t.ok(control.div.innerHTML != "", 
+            "Shows the position after activate and move");
+        
+        map.destroy();     
+    }
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/Navigation.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/Navigation.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/Navigation.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -71,6 +71,28 @@
         OpenLayers.Control.prototype.destroy = temp;
     }
 
+    function test_Control_Navigation_disableZoomBox(t) {
+        t.plan(2);
+        var nav = new OpenLayers.Control.Navigation();
+        var zb = new OpenLayers.Control.ZoomBox({});
+        nav.zoomBox = zb;
+        zb.activate();
+        nav.disableZoomBox();
+        t.eq(nav.zoomBoxEnabled, false, "zoom box deactivated");
+        t.eq(zb.active, false, "zoom box control deactivated");
+    }
+
+    function test_Control_Navigation_enableZoomBox(t) {
+        t.plan(2);
+        var nav = new OpenLayers.Control.Navigation();
+        var zb = new OpenLayers.Control.ZoomBox({});
+        nav.zoomBox = zb;
+        nav.active = true;
+        nav.enableZoomBox();
+        t.eq(nav.zoomBoxEnabled, true, "zoom box activated");
+        t.eq(zb.active, true, "zoom box control activated");
+    }
+
     function test_Control_Navigation_disableZoomWheel(t) {
         t.plan(2);
         var nav = new OpenLayers.Control.Navigation();
@@ -96,7 +118,34 @@
         t.eq(nav.zoomWheelEnabled, true, "mouse wheel activated");
         t.eq(wheel.active, true, "mouse wheel handler activated");
     }
+    
+    function test_documentDrag(t) {
+        
+        t.plan(2);
 
+        /**
+         * These tests confirm that the documentDrag property is false by 
+         * default and is passed on to the DragPan control.  Tests of panning
+         * while dragging outside the viewport should go in the DragPan tests.
+         * Tests of the document events and appropriate callbacks from the 
+         * handler should go in the Drag handler tests.
+         */
+         
+         var nav = new OpenLayers.Control.Navigation();
+         t.eq(nav.documentDrag, false, "documentDrag false by default");
+         // nav.destroy(); // fails if called before draw
+         
+         var map = new OpenLayers.Map({
+             div: document.body,
+             controls: [new OpenLayers.Control.Navigation({documentDrag: true})]
+         });
+         nav = map.controls[0];
+
+         t.eq(nav.dragPan.documentDrag, true, "documentDrag set on the DragPan control");
+         map.destroy();
+         
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/NavigationHistory.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/NavigationHistory.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/NavigationHistory.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -168,6 +168,75 @@
         
     }
 
+    function test_clear(t) {
+        t.plan(7);
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer(
+            "test", {isBaseLayer: true}
+        );
+        map.addLayer(layer);
+        map.zoomToMaxExtent();
+
+        var control = new OpenLayers.Control.NavigationHistory();
+        map.addControl(control);
+        
+        t.ok(!control.previous.active, "previous control not active");
+        t.ok(!control.next.active, "next control not active");
+
+        map.zoomTo(4);
+        t.ok(control.previous.active, "previous control is active after a move");
+        t.ok(!control.next.active, "next control is not active after a move");
+
+        control.clear();
+        t.eq(control.previousStack.length + control.nextStack.length, 0, "stacks are empty after a clear");
+        t.ok(!control.previous.active, "previous control not active after a clear");
+        t.ok(!control.next.active, "next control not active after a clear");
+
+        control.destroy();
+    }
+
+    function test_reprojection(t) {
+        t.plan(2);
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer(
+            "test", {isBaseLayer: true}
+        );
+        map.addLayer(layer);
+        map.zoomToMaxExtent();
+
+        var control = new OpenLayers.Control.NavigationHistory();
+        map.addControl(control);
+
+        map.zoomTo(4);
+        var bounds = map.getExtent().clone();
+        var expected = bounds.transform(new OpenLayers.Projection('EPSG:4326'),
+            new OpenLayers.Projection('EPSG:900913'));
+        // change the projection to EPSG:900913
+        var projSettings = {
+            units: "m", 
+            maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508), 
+            maxResolution: 156543.0339
+        };
+        map.setOptions(projSettings);
+        map.projection = 'EPSG:900913';
+        delete projSettings.maxResolution;
+        projSettings.projection = new OpenLayers.Projection('EPSG:900913');
+        layer.addOptions(projSettings);
+        layer.initResolutions();
+
+        map.zoomTo(7);
+
+        // go back one in the history
+        control.previous.trigger();
+
+        t.eq(map.getExtent().left.toFixed(3), expected.left.toFixed(3), "The extent [left] is reprojected correctly");
+        t.eq(map.getExtent().right.toFixed(3), expected.right.toFixed(3), "The extent [right] is reprojected correctly");
+        // top and bottom cannot be checked here since in EPSG:900913 the extent is not a rectangle so they are adjusted.
+
+        control.destroy();
+
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/OverviewMap.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/OverviewMap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/OverviewMap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,7 +2,7 @@
 <head>
   <script src="../../lib/OpenLayers.js"></script>
   <script type="text/javascript">
-    var map; 
+    var map, control;
     function test_initialize(t) {
         t.plan( 2 );
     
@@ -10,6 +10,81 @@
         t.ok( control instanceof OpenLayers.Control.OverviewMap, "new OpenLayers.Control.OverviewMap returns object" );
         t.eq( control.displayClass,  "olControlOverviewMap", "displayClass is correct" );
     }
+
+    function test_setMap(t) {
+        t.plan(4);
+
+        var setMapTest = function(map) {
+            t.ok(true, "Handler.setMap called for " + this.CLASS_NAME);
+            this.map = map;        
+        };
+        var drag_setMap = OpenLayers.Handler.Drag.prototype.setMap;
+        OpenLayers.Handler.Drag.prototype.setMap = setMapTest;
+        var click_setMap = OpenLayers.Handler.Click.prototype.setMap;
+        OpenLayers.Handler.Click.prototype.setMap = setMapTest;
+
+        map = new OpenLayers.Map('map', {
+            layers  : [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+            controls: []
+        });
+        control = new OpenLayers.Control.OverviewMap();
+    
+        map.addControl(control);
+
+        map.zoomToMaxExtent();
+        t.eq(control.handlers.drag.map.id, control.ovmap.id, "drag.map is correct");
+        t.eq(control.handlers.click.map.id, control.ovmap.id, "click.map is correct");
+
+        map.destroy();
+        OpenLayers.Handler.Drag.prototype.setMap = drag_setMap;
+        OpenLayers.Handler.Click.prototype.setMap = click_setMap;
+    }
+
+    function test_destroy(t) {
+        t.plan(6);
+
+        // set up
+
+        var log_drag = [], log_click = [], control;
+
+        map = new OpenLayers.Map('map');
+        map.addLayer(new OpenLayers.Layer("layer", {isBaseLayer: true}));
+
+        control = new OpenLayers.Control.OverviewMap();
+        map.addControl(control);
+
+        map.zoomToMaxExtent();
+
+        control.handlers.drag.destroy = function() {
+            log_drag.push({"map": !!this.map.events});
+        };
+        control.handlers.click.destroy = function() {
+            log_click.push({"map": !!this.map.events});
+        };
+
+        // test
+
+        control.destroy();
+        t.eq(log_drag.length, 2,
+             "destroy() destroys drag handler twice, expected");
+        if (log_drag.length == 2) {
+            t.eq(log_drag[0].map, true,
+                 "destroy() destroys drag handler before ovmap is destroyed (0)");
+            t.eq(log_drag[1].map, false,
+                 "destroy() destroys drag handler after ovmap is destroyed (1)");
+        }
+        t.eq(log_click.length, 2,
+             "destroy() destroys click handler twice, expected");
+        if (log_click.length == 2) {
+            t.eq(log_click[0].map, true,
+                 "destroy() destroys click handler before ovmap is destroyed (0)");
+            t.eq(log_click[1].map, false,
+                 "destroy() destroys click handler after ovmap is destroyed (1)");
+        }
+
+        // tear down
+        map.destroy();
+    }
     function test_addControl (t) {
         t.plan( 6 );
         map = new OpenLayers.Map('map');
@@ -72,6 +147,32 @@
         });
     }
 
+    function test_initialize_maximized(t) {
+        t.plan(4);
+
+        control = new OpenLayers.Control.OverviewMap()
+        map = new OpenLayers.Map('map', {
+            layers  : [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+            controls: [control]
+        });
+        
+        t.eq(control.maximized, false, "OverviewMap is not maximized by default");
+        t.eq(control.element.style.display, 'none', "OverviewMap.element is not visible");
+        map.destroy();
+
+        control = new OpenLayers.Control.OverviewMap({
+            maximized: true
+        })
+        map = new OpenLayers.Map('map', {
+            layers  : [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+            controls: [control]
+        });
+        t.eq(control.maximized, true, "OverviewMap.maximized is set");
+        t.eq(control.element.style.display, '', "OverviewMap.element is visible");
+
+        map.destroy();
+    }
+
   </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Control/PanPanel.html (from rev 10919, trunk/openlayers/tests/Control/PanPanel.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Control/PanPanel.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Control/PanPanel.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,23 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+    function test_constructor (t) {
+        t.plan(1);
+        
+        // set up
+        var control;
+
+        // tests
+        control = new OpenLayers.Control.PanPanel({slideFactor: 200});
+        t.ok(control.controls[0].slideFactor == 200 &&
+             control.controls[1].slideFactor == 200 &&
+             control.controls[2].slideFactor == 200 &&
+             control.controls[3].slideFactor == 200,
+             "ctor sets slideFactor in all Pan controls");
+    }
+  </script>
+</head>
+<body>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Control/PanZoom.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/PanZoom.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/PanZoom.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -43,7 +43,7 @@
 
     function test_Control_PanZoom_control_events (t) {
 
-        if ( !window.document.createEvent || OpenLayers.Util.getBrowserName() == "opera" || !t.open_window) {
+        if ( !window.document.createEvent || OpenLayers.BROWSER_NAME == "opera" || !t.open_window) {
             //ie can't simulate mouseclicks
             t.plan(0);
             t.debug_print("FIXME: This browser does not support the PanZoom test at this time.");

Modified: sandbox/ahocevar/playground/tests/Control/PanZoomBar.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/PanZoomBar.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/PanZoomBar.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,20 +2,20 @@
 <head>
   <script src="../../lib/OpenLayers.js"></script>
   <script type="text/javascript">
-    var map; 
+    var map;
     function test_Control_PanZoomBar_constructor (t) {
         t.plan( 4 );
-    
+
         control = new OpenLayers.Control.PanZoomBar({position: new OpenLayers.Pixel(100,100)});
         t.ok( control instanceof OpenLayers.Control.PanZoomBar, "new OpenLayers.Control.PanZoomBar returns object" );
         t.eq( control.displayClass,  "olControlPanZoomBar", "displayClass is correct" );
-        t.eq( control.position.x, 100, "PanZoom X Set correctly."); 
-        t.eq( control.position.y, 100, "PanZoom y Set correctly."); 
+        t.eq( control.position.x, 100, "PanZoom X Set correctly.");
+        t.eq( control.position.y, 100, "PanZoom y Set correctly.");
     }
     function test_Control_PanZoomBar_addControl (t) {
         t.plan( 8 );
         map = new OpenLayers.Map('map', {controls:[]});
-        var layer = new OpenLayers.Layer.WMS("Test Layer", 
+        var layer = new OpenLayers.Layer.WMS("Test Layer",
             "http://octo.metacarta.com/cgi-bin/mapserv?",
             {map: "/mapdata/vmap_wms.map", layers: "basic"});
         map.addLayer(layer);
@@ -33,11 +33,11 @@
         map.addControl(control2, new OpenLayers.Pixel(100,100));
         t.eq( control2.div.style.top, "100px", "2nd control div is located correctly");
     }
-    
+
     function test_Control_PanZoomBar_clearDiv(t) {
         t.plan(2);
         map = new OpenLayers.Map('map', {controls:[]});
-        var layer = new OpenLayers.Layer.WMS("Test Layer", 
+        var layer = new OpenLayers.Layer.WMS("Test Layer",
             "http://octo.metacarta.com/cgi-bin/mapserv?",
             {map: "/mapdata/vmap_wms.map", layers: "basic"});
         map.addLayer(layer);
@@ -48,11 +48,11 @@
         t.eq(control.div.childNodes.length, 0, "control's div cleared.");
         t.eq(control.zoombarDiv, null, "zoombar div nullified.")
     }
-    
+
     function test_Control_PanZoomBar_divClick (t) {
         t.plan(2);
         map = new OpenLayers.Map('map', {controls:[]});
-        var layer = new OpenLayers.Layer.WMS("Test Layer", 
+        var layer = new OpenLayers.Layer.WMS("Test Layer",
             "http://octo.metacarta.com/cgi-bin/mapserv?",
             {map: "/mapdata/vmap_wms.map", layers: "basic"});
         map.addLayer(layer);
@@ -64,9 +64,23 @@
         map.fractionalZoom = true;
         control.divClick({'xy': {'x': 0, 'y': 49}, which: 1});
         t.eq(map.zoom.toFixed(3), '10.545', "zoom is correct on fractional zoom map");
-    
+
     }
 
+    function test_Control_PanZoomBar_forceFixedZoomLevel_divClick (t) {
+        t.plan(1);
+        map = new OpenLayers.Map('map', {controls:[], fractionalZoom: true});
+        var layer = new OpenLayers.Layer.WMS("Test Layer",
+            "http://octo.metacarta.com/cgi-bin/mapserv?",
+            {map: "/mapdata/vmap_wms.map", layers: "basic"});
+        map.addLayer(layer);
+        control = new OpenLayers.Control.PanZoomBar({forceFixedZoomLevel: true});
+        map.addControl(control);
+
+        control.divClick({'xy': {'x': 0, 'y': 49}, which: 1});
+        t.eq(map.zoom, 11, "forceFixedZoomLevel makes sure only fixed zoom levels are used even if the map has fractionalZoom");
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Control/Panel.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/Panel.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/Panel.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -9,10 +9,9 @@
         t.ok( control instanceof OpenLayers.Control.Panel, "new OpenLayers.Control returns object" );
         t.eq( control.displayClass,  "olControlPanel", "displayClass is correct" );
     }
-    function test_Control_Panel_constructor (t) {
-        t.plan(6);
+    function test_Control_Panel_constructor2 (t) {
+        t.plan(16);
         var map = new OpenLayers.Map('map');
-        var panel = new OpenLayers.Control.Panel();
         var toolControl = new OpenLayers.Control.ZoomBox();
         var AnotherToolControl = OpenLayers.Class(OpenLayers.Control, {
               CLASS_NAME: 'mbControl.TestTool',
@@ -23,32 +22,73 @@
               CLASS_NAME: 'mbControl.TestToggle',
               type: OpenLayers.Control.TYPE_TOGGLE
         });
+        
         var toggleControl = new ToggleControl();
+        var buttonControl = new OpenLayers.Control.Button({
+            trigger: function () {
+                t.ok(true, "trigger function of button is called.");     
+            }
+        });
 
+        var panel = new OpenLayers.Control.Panel(
+            {defaultControl: anotherToolControl});
         t.ok(panel instanceof OpenLayers.Control.Panel, 
               "new OpenLayers.Control.Panel returns object");
+        panel.redraw = function(){
+            panel.redrawsCount++;            
+        };
 
         panel.addControls([toolControl, anotherToolControl, toggleControl]);
-
         t.eq(panel.controls.length, 3,
               "added three controls to the panel");
+        panel.addControls([buttonControl]);
+
+        panel.redrawsCount = 0;              
         map.addControl(panel);
+        t.ok((panel.redrawsCount > 0), "Redraw called on add panel to map " + 
+            panel.redrawsCount + " times.");        
+        t.ok((panel.active),"Panel is active after add panel to map.");        
+        
+        panel.redrawsCount = 0;              
+        panel.addControls(new AnotherToolControl());
+        t.ok((panel.redrawsCount > 0),
+            "Redraw called on add control to panel after add panel to map " +
+            panel.redrawsCount + " times."); 
 
+        panel.deactivate();
+        panel.redrawsCount = 0;                      
+        panel.activate();        
+        t.ok((panel.redrawsCount > 0),"Redraw called on activate panel " +
+            panel.redrawsCount + " times."); 
+
         panel.activateControl(toolControl);
-        t.ok(toolControl.active && !anotherToolControl.active && !toggleControl.active,
-              "activated one tool control, the other one is inactive and the toggle control also.");
+        t.ok(toolControl.active && !anotherToolControl.active && !toggleControl.active && !buttonControl.active,
+              "activated one tool control, the other one is inactive and the toggle & button controls also.");
 
-        panel.redraw = function(){
-            t.ok(true,"Redraw called on activated toggle");
-        }
-              
+        panel.redrawsCount = 0;              
         panel.activateControl(toggleControl);
+        t.eq(panel.redrawsCount, 1, "Redraw called on activated toggle " +
+            panel.redrawsCount + " times.");
         t.ok(toolControl.active && !anotherToolControl.active && toggleControl.active,
-              "activated the toggle control, which has no influence on the tool controls.");
+              "activated the toggle control, which has no influence on the tool & togggle controls.");
+        panel.activateControl(buttonControl);
+        t.ok(toolControl.active && !anotherToolControl.active && toggleControl.active,
+              "activateContol calling for button, which has no influence on the tool & togggle controls.");
+        t.ok(!buttonControl.active,
+              "activateContol calling for button, button remains inactive.");
+        buttonControl.activate();
+        t.ok(buttonControl.active && toolControl.active && !anotherToolControl.active && toggleControl.active,
+              "activated the button control, which has no influence on the tool & togggle controls.");
               
+        panel.redrawsCount = 0; 
         panel.activateControl(anotherToolControl);
+        t.ok((panel.redrawsCount > 0),
+            "Redraw called on activated tool control " + panel.redrawsCount + 
+            " times.");
         t.ok(!toolControl.active && anotherToolControl.active && toggleControl.active,
               "activated the other tool control, the first one is inactive and the toggle control still active.");
+        t.ok(buttonControl.active,
+              "activated the other tool control, the button control still active.");
     }
     function test_Control_Panel_titles (t) { 
         t.plan(2); 
@@ -117,7 +157,91 @@
 
 
     }
+    
+    function test_Control_Panel_saveState (t) { 
+        t.plan(11); 
+        var map = new OpenLayers.Map('map');
 
+        var defaultControl = new OpenLayers.Control();
+        var panel = new OpenLayers.Control.Panel({
+            defaultControl: defaultControl
+        });
+        panel.addControls([new OpenLayers.Control(), defaultControl]);
+        map.addControl(panel);
+        t.eq(defaultControl.active, true,
+            "After panel activation default control is active.");    
+        t.ok(panel.defaultControl,
+            "defaultControl not nullified after initial panel activation");          
+        // activate the 1st control
+        panel.activateControl(panel.controls[0]);
+        panel.deactivate();      
+        t.ok(!panel.controls[0].active && !panel.controls[1].active,
+            "No controls are active after panel deactivation.");
+        panel.activate();   
+        t.eq(panel.controls[0].active, false,
+            "After panel reactivation first control is inactive.");              
+        t.eq(panel.controls[1].active, true,
+            "After panel reactivation default control is active again.");
+        panel.destroy();
+
+        defaultControl = new OpenLayers.Control();
+        panel = new OpenLayers.Control.Panel({
+            saveState: true,
+            defaultControl: defaultControl
+        });
+        panel.addControls([new OpenLayers.Control(), defaultControl]);
+        map.addControl(panel);
+        t.eq(defaultControl.active, true,
+            "After panel activation default control is active.");    
+        t.eq(panel.defaultControl, null,
+            "defaultControl nullified after initial panel activation");          
+        // activate the 1st control, which will deactivate the 2nd
+        panel.activateControl(panel.controls[0]);
+        t.eq(panel.controls[1].active, false,
+            "2nd control deactivated with activation of 1st");
+        panel.deactivate();      
+        t.ok(!panel.controls[0].active && !panel.controls[1].active,
+            "No controls are active after panel deactivation.");
+        panel.activate();   
+        t.eq(panel.controls[0].active, true,
+            "After panel reactivation first control is active.");
+        t.eq(panel.controls[1].active, false,
+            "After panel reactivation second control is inactive.");              
+        panel.destroy();
+        map.destroy();
+    } 
+
+    function test_Control_Panel_autoActivate (t) {
+        t.plan(1);
+        var map = new OpenLayers.Map('map');
+        var controlNoDeactive = new OpenLayers.Control({autoActivate:true});
+        var chkDeactivate = function () {
+            t.ok(false, "Tool control autoActivate:true was deactivated unnecessarily");
+        };
+        controlNoDeactive.events.on({deactivate: chkDeactivate});
+        var panel = new OpenLayers.Control.Panel();
+        
+        map.addControl(panel);
+        panel.addControls([controlNoDeactive]);
+        controlNoDeactive.events.un({deactivate: chkDeactivate});
+        t.ok(!controlNoDeactive.active, "Tool control autoActivate:true is not active");
+        
+    }
+    function test_Control_Panel_deactivate (t) {
+        t.plan(2);
+        var map = new OpenLayers.Map('map');
+        var control = new OpenLayers.Control();
+        var panel = new OpenLayers.Control.Panel();        
+        map.addControl(panel);
+        panel.addControls([control]);        
+        t.ok(panel.div.innerHTML != "", "Panel displayed after activate");        
+        
+        panel.deactivate();
+        t.ok(panel.div.innerHTML == "", 
+            "Panel is not displayed after deactivate without any active control");
+
+        map.destroy();
+    }
   </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Control/SLDSelect.html (from rev 10919, trunk/openlayers/tests/Control/SLDSelect.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Control/SLDSelect.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Control/SLDSelect.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,183 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(11);
+        var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Click);
+        t.eq(control.handler instanceof OpenLayers.Handler.Click, true, "Click handler created");
+        t.ok(control.handler.callbacks["click"] === control.select, "Click callback correctly set");
+        control.destroy();
+        control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {handlerOptions: {irregular: true}});
+        t.eq(control.handler instanceof OpenLayers.Handler.RegularPolygon, true, "RegularPolygon handler created");
+        t.eq(control.handler.irregular, true, "RegularPolygon handler is irregular");
+        t.eq(control.handler.persist, false, "RegularPolygon handler is not persistant");
+        t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set");
+        control.destroy();
+        control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Polygon);
+        t.eq(control.handler instanceof OpenLayers.Handler.Polygon, true, "Polygon handler created");
+        t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set");
+        control.destroy();
+        control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Path);
+        t.eq(control.handler instanceof OpenLayers.Handler.Path, true, "Path handler created");
+        t.ok(control.handler.callbacks["done"] === control.select, "Done callback correctly set");
+        control.destroy();
+        var layer = new OpenLayers.Layer.WMS('Foo', 'http://foo', {LAYERS: 'A'});
+        control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {layers: [layer]});
+        t.eq(control.layers.length, 1, "Layers property correctly set");
+        control.destroy();
+        layer.destroy();
+    }
+
+    function test_select(t) {
+        t.plan(9);
+        var parser = new OpenLayers.Format.WFSDescribeFeatureType();
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.WMS('Foo', 'http://foo', {LAYERS: 'AAA64'});
+        map.addLayer(layer);
+
+        var text =
+            '<?xml version="1.0" encoding="ISO-8859-1" ?>' +
+            '<schema' +
+            '   targetNamespace="http://mapserver.gis.umn.edu/mapserver" ' +
+            '   xmlns:rws="http://mapserver.gis.umn.edu/mapserver" ' +
+            '   xmlns:ogc="http://www.opengis.net/ogc"' +
+            '   xmlns:xsd="http://www.w3.org/2001/XMLSchema"' +
+            '   xmlns="http://www.w3.org/2001/XMLSchema"' +
+            '   xmlns:gml="http://www.opengis.net/gml"' +
+            '   elementFormDefault="qualified" version="0.1" >' +
+            '  <import namespace="http://www.opengis.net/gml"' +
+            '          schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" />' +
+            '  <element name="AAA64" ' +
+            '           type="rws:AAA64Type" ' +
+            '           substitutionGroup="gml:_Feature" />' +
+            '  <complexType name="AAA64Type">' +
+            '    <complexContent>' +
+            '      <extension base="gml:AbstractFeatureType">' +
+            '        <sequence>' +
+            '          <element name="geometry" type="gml:MultiLineStringPropertyType" minOccurs="0" maxOccurs="1"/>' +
+            '          <element name="OBJECTID" type="string"/>' +
+            '        </sequence>' +
+            '      </extension>' +
+            '    </complexContent>' +
+            '  </complexType>' +
+            '</schema>';
+
+        OpenLayers.Control.SLDSelect.prototype.wfsCache[layer.id] = parser.read(text);
+        var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon,
+            {layers: [layer], clearOnDeactivate: true, handlerOptions: {irregular: true} });
+
+        var testEvent = function(evt) {
+            t.eq(evt.filters.length, 1, "Event has a filters array set");
+            t.eq(evt.filters[0] instanceof OpenLayers.Filter.Spatial, true, "Spatial filter has been created");
+        };
+
+        control.events.register("selected", this, testEvent);
+        map.addControl(control);
+        var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon(
+            new OpenLayers.Geometry.Point(0, 0), 5, 4);
+        control.select(geometry);
+        control.events.unregister("selected", this, testEvent);
+        t.eq(map.layers.length, 2, "Selection layer has been created and added to the map");
+        t.eq(map.layers[1] instanceof OpenLayers.Layer.WMS, true, "A WMS layer has been created as the selection layer");
+        t.eq(map.layers[1].tileOptions.maxGetUrlLength, 2048, "Selection layer will automatically switch to HTTP Post if content gets longer than 2048");
+        var expected_sld = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>AAA64</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:LineSymbolizer><sld:Stroke><sld:CssParameter name="stroke">#FF0000</sld:CssParameter><sld:CssParameter name="stroke-width">2</sld:CssParameter></sld:Stroke></sld:LineSymbolizer></sld:Rule></sld:Featur
 eTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>';
+
+        t.xml_eq(map.layers[1].params.SLD_BODY, expected_sld, "SLD generated correctly");
+
+        var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon(
+            new OpenLayers.Geometry.Point(0, 0), 7, 4);
+        control.select(geometry);
+        t.eq(map.layers.length, 2, "Selection layer is reused when new selection is performed");
+
+        map.layers[0].setVisibility(false);
+        t.eq(map.layers[1].getVisibility(), false, "Visibility of selection layer is synchronized with source layer");
+        // activate would issue a SLD WMS DescribeLayer request and we are bypassing this here
+        control.active = true;
+        control.deactivate();
+        t.eq(map.layers.length, 1, "Selection layer is removed on deactive if clearOnDeactivate is set to true");
+        map.destroy();
+    }
+
+    function test_multiselect(t) {
+        t.plan(2);
+
+        var parser = new OpenLayers.Format.WFSDescribeFeatureType();
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.WMS('Multi', 'http://foo', {LAYERS: 'KGNAT.VKUNSTWERK,KGNAT.LKUNSTWERK,KGNAT.PKUNSTWERK'});
+        map.addLayer(layer);
+
+        var text =
+            '<?xml version="1.0" encoding="ISO-8859-1" ?>' +
+            '<schema' +
+            '   targetNamespace="http://mapserver.gis.umn.edu/mapserver" ' +
+            '   xmlns:rws="http://mapserver.gis.umn.edu/mapserver" ' +
+            '   xmlns:ogc="http://www.opengis.net/ogc"' +
+            '   xmlns:xsd="http://www.w3.org/2001/XMLSchema"' +
+            '   xmlns="http://www.w3.org/2001/XMLSchema"' +
+            '   xmlns:gml="http://www.opengis.net/gml"' +
+            '   elementFormDefault="qualified" version="0.1" >' +
+            '  <import namespace="http://www.opengis.net/gml"' +
+            '          schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" />' +
+            '  <element name="KGNAT.VKUNSTWERK" ' +
+            '           type="rws:KGNAT.VKUNSTWERKType" ' +
+            '           substitutionGroup="gml:_Feature" />' +
+            '  <complexType name="KGNAT.VKUNSTWERKType">' +
+            '    <complexContent>' +
+            '      <extension base="gml:AbstractFeatureType">' +
+            '        <sequence>' +
+            '          <element name="geometry" type="gml:MultiPolygonPropertyType" minOccurs="0" maxOccurs="1"/>' +
+            '        </sequence>' +
+            '      </extension>' +
+            '    </complexContent>' +
+            '  </complexType>' +
+            '  <element name="KGNAT.LKUNSTWERK" ' +
+            '           type="rws:KGNAT.LKUNSTWERKType" ' +
+            '           substitutionGroup="gml:_Feature" />' +
+            '  <complexType name="KGNAT.LKUNSTWERKType">' +
+            '    <complexContent>' +
+            '      <extension base="gml:AbstractFeatureType">' +
+            '        <sequence>' +
+            '          <element name="geometry" type="gml:MultiLineStringPropertyType" minOccurs="0" maxOccurs="1"/>' +
+            '        </sequence>' +
+            '      </extension>' +
+            '    </complexContent>' +
+            '  </complexType>' +
+            '  <element name="KGNAT.PKUNSTWERK" ' +
+            '           type="rws:KGNAT.PKUNSTWERKType" ' +
+            '           substitutionGroup="gml:_Feature" />' +
+            '  <complexType name="KGNAT.PKUNSTWERKType">' +
+            '    <complexContent>' +
+            '      <extension base="gml:AbstractFeatureType">' +
+            '        <sequence>' +
+            '          <element name="geometry" type="gml:MultiPointPropertyType" minOccurs="0" maxOccurs="1"/>' +
+            '        </sequence>' +
+            '      </extension>' +
+            '    </complexContent>' +
+            '  </complexType>' +
+            '</schema>';
+
+        OpenLayers.Control.SLDSelect.prototype.wfsCache[layer.id] = parser.read(text);
+        var control = new OpenLayers.Control.SLDSelect(OpenLayers.Handler.RegularPolygon, {handlerOptions: {irregular: true}, layers: [layer]});
+        var testEvent = function(evt) {
+            t.eq(evt.filters.length, 3, "Event has a filters array set with length tree");
+        };
+        control.events.register("selected", this, testEvent);
+
+        map.addControl(control);
+        var geometry = OpenLayers.Geometry.Polygon.createRegularPolygon(
+            new OpenLayers.Geometry.Point(0, 0), 5, 4);
+        control.select(geometry);
+        var expected_sld = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>KGNAT.VKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:PolygonSymbolizer><sld:Fill><sld:CssParameter name="fill">#FF0000</sld:CssParameter></sld:Fill></sld:PolygonSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer><sl
 d:NamedLayer><sld:Name>KGNAT.LKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:LineSymbolizer><sld:Stroke><sld:CssParameter name="stroke">#FF0000</sld:CssParameter><sld:CssParameter name="stroke-width">2</sld:CssParameter></sld:Stroke></sld:LineSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer><sld:NamedLayer><sld:Name>KGNAT.PKUNSTWERK</sld:Name><sld:UserStyle><sld:Name>default</sld:Name><sld:FeatureTypeStyle><sld:Rule><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>geometry</ogc:PropertyName><gml:Box xmlns:gml="http://www.opengis.net/gml"><gml:coordinates de
 cimal="." cs="," ts=" ">-3.5355339059327,-3.5355339059327 3.5355339059327,3.5355339059327</gml:coordinates></gml:Box></ogc:BBOX></ogc:Filter><sld:PointSymbolizer><sld:Graphic><sld:Mark><sld:WellKnownName>square</sld:WellKnownName><sld:Fill><sld:CssParameter name="fill">#FF0000</sld:CssParameter></sld:Fill><sld:Stroke/></sld:Mark><sld:Size>10</sld:Size></sld:Graphic></sld:PointSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>';
+
+        t.xml_eq(map.layers[1].params.SLD_BODY, expected_sld, "SLD generated correctly");
+        map.destroy();
+    }
+    
+  </script>
+</head>
+<body>
+    <div id="map" style="width: 100px; height: 100px;"></div>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Control/ScaleLine.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/ScaleLine.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/ScaleLine.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,8 @@
 <html>
 <head>
-  <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAA9XNhd8q0UdwNC7YSO4YZghSPUCi5aRYVveCcVYxzezM4iaj_gxQ9t-UajFL70jfcpquH5l1IJ-Zyyw'></script>
+    <script type="text/javascript">var oldAlert = window.alert, gMess; window.alert = function(message) {gMess = message; return true;};</script>
+    <!-- this gmaps key generated for http://openlayers.org/dev/ -->
+    <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAA9XNhd8q0UdwNC7YSO4YZghSPUCi5aRYVveCcVYxzezM4iaj_gxQ9t-UajFL70jfcpquH5l1IJ-Zyyw'></script>
   <script src="../../lib/OpenLayers.js"></script>
   <script type="text/javascript">
   var validkey = (window.location.protocol == "file:") ||
@@ -162,10 +164,6 @@
                           window.location.host);          
         }
 
-        var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.Google('Goog Layer');
-        map.addLayer(layer);
-        
         map.destroy();
     }   
     function test_ie_oneunit(t) {
@@ -183,7 +181,7 @@
   </script>
 </head>
 <body>
-    <a id="ScaleLine" href="">ScaleLine</a> <br />
+    <a id="ScaleLine" href="">ScaleLine</a> <br/>
     <div id="map" style="width: 1024px; height: 512px;"/>
 </body>
 </html>

Modified: sandbox/ahocevar/playground/tests/Control/SelectFeature.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/SelectFeature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/SelectFeature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,16 +12,16 @@
         t.ok(control instanceof OpenLayers.Control.SelectFeature,
              "new OpenLayers.Control.SelectFeature returns an instance");
         t.eq(control.layers[0], "bar",
-             "constructor with array of layers sets layer correctly");        
+             "constructor with array of layers sets layer correctly");
 //        t.eq(control.handlers.feature.geometryTypes, "foo",
 //             "constructor sets options correctly on feature handler");
         t.ok(control.layer instanceof OpenLayers.Layer.Vector.RootContainer, "control has a root container layer if constructor was called with an array of layers");
-        
+
         control = new OpenLayers.Control.SelectFeature(layer, options);
         t.eq(control.layers, null, "this.layers is null if constructor called with a single layer");
         t.eq(control.layer, layer, "this.layer holds the layer that was passed with the constructor if called with a single layer")
     }
-    
+
     function test_Control_SelectFeature_destroy(t) {
         t.plan(2);
         var map = new OpenLayers.Map("map");
@@ -38,9 +38,9 @@
         }
 // should nullify the layer property here
         control.destroy();
-        
+
     }
-    
+
     function test_Control_SelectFeature_select(t) {
         t.plan(4);
         var map = new OpenLayers.Map("map");
@@ -66,7 +66,7 @@
         control.unselect(feature2);
         t.eq(feature2.renderIntent, "default", "render intent is set back to default");
     }
-    
+
     function test_Control_SelectFeature_clickFeature(t) {
         t.plan(6);
         // mock up layer
@@ -92,7 +92,7 @@
                 layer: layer
             };
         }
-        
+
         // test that onSelect gets called properly
         control.onSelect = function(feature) {
             feature.tested += 1;
@@ -108,11 +108,11 @@
             feature.tested += 1;
             t.eq(feature.id, features[feature.index].id,
                  "onUnselect called with proper feature (" + feature.index + ")");
-            t.eq(feature.tested, feature.test, 
+            t.eq(feature.tested, feature.test,
                  "onUnselect called only once for feature (" + feature.index + ")");
             t.ok(this == control, "onUnselect called in the scope of the control if control.scope is not provided");
         }
-        
+
         // mock up first click on first feature (runs 3 tests from onSelect)
         var feature = features[0];
         feature.index = 0;
@@ -128,9 +128,9 @@
         feature.test = 2;
         control.clickFeature(feature);
 
-        
+
     }
-    
+
     function test_box(t) {
         t.plan(5);
         var map = new OpenLayers.Map("map");
@@ -149,30 +149,30 @@
         control.setMap(map);
         map.getLonLatFromPixel = function(arg) {
             return new OpenLayers.LonLat(arg.x, arg.y);
-        }    
+        }
         control.selectBox(new OpenLayers.Bounds(-1, -1, 2, 2));
         t.eq(layer.selectedFeatures.length, 3, "box around all features selects 3 features");
-        
+
         control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1));
-        t.eq(layer.selectedFeatures.length, 4, "box around other features doesn't turn off already selected features.");        
-        
+        t.eq(layer.selectedFeatures.length, 4, "box around other features doesn't turn off already selected features.");
+
         control.multipleSelect = function() {
             return false;
         };
         control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1));
         t.eq(layer.selectedFeatures.length, 1, "box around other features correctly turns off already selected features.");
-        
+
         control.geometryTypes = null;
         control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100));
         t.eq(layer.selectedFeatures.length, layer.features.length, "all features selected with no geometryTypes filter");
-        
+
         control.geometryTypes = ["OpenLayers.Geometry.Point"];
         control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100));
         t.eq(layer.selectedFeatures.length, 3, "3 features selected with geometryTypes filter");
-        
 
+
     }
-    
+
     function test_Control_SelectFeature_activate(t) {
         t.plan(4);
         var map = new OpenLayers.Map("map");
@@ -267,9 +267,9 @@
         t.eq(feature.renderIntent, "temporary",
              "feature drawn with expected render intent after \"mouseover\"");
         t.eq(feature._lastHighlighter, ctrl2.id,
-             "feature._lastHighlighter properly set after \"mouseover\""); 
+             "feature._lastHighlighter properly set after \"mouseover\"");
         t.eq(feature._prevHighlighter, undefined,
-             "feature._prevHighlighter properly set after \"mouseover\""); 
+             "feature._prevHighlighter properly set after \"mouseover\"");
 
         // click in feature, feature is drawn with "select"
         _feature = feature;
@@ -278,9 +278,9 @@
         t.eq(feature.renderIntent, "select",
              "feature drawn with expected render intent after \"clickin\"");
         t.eq(feature._lastHighlighter, ctrl1.id,
-             "feature._lastHighlighter properly set after \"clickin\""); 
+             "feature._lastHighlighter properly set after \"clickin\"");
         t.eq(feature._prevHighlighter, ctrl2.id,
-             "feature._prevHighlighter properly set after \"clickin\""); 
+             "feature._prevHighlighter properly set after \"clickin\"");
 
         // mouse out of feature, feature is still drawn with "select"
         _feature = null;
@@ -289,9 +289,9 @@
         t.eq(feature.renderIntent, "select",
              "feature drawn with expected render intent after \"mouseout\"");
         t.eq(feature._lastHighlighter, ctrl1.id,
-             "feature._lastHighlighter properly set after \"nouseout\""); 
+             "feature._lastHighlighter properly set after \"nouseout\"");
         t.ok(feature._prevHighlighter, ctrl2.id,
-             "feature._prevHighlighter properly set after \"mouseout\""); 
+             "feature._prevHighlighter properly set after \"mouseout\"");
 
         // mouse over feature again, feature is drawn with "temporary"
         _feature = feature;
@@ -300,9 +300,9 @@
         t.eq(feature.renderIntent, "temporary",
              "feature drawn with expected render intent after \"mouseover\"");
         t.eq(feature._lastHighlighter, ctrl2.id,
-             "feature._lastHighlighter properly set after \"mouseover\""); 
+             "feature._lastHighlighter properly set after \"mouseover\"");
         t.eq(feature._prevHighlighter, ctrl1.id,
-             "feature._prevHighlighter properly set after \"mouseover\""); 
+             "feature._prevHighlighter properly set after \"mouseover\"");
 
         // mouve out of feature again, feature is still drawn with "select"
         _feature = null;
@@ -311,9 +311,9 @@
         t.eq(feature.renderIntent, "select",
              "feature drawn with expected render intent after \"mouseout\"");
         t.eq(feature._lastHighlighter, ctrl1.id,
-             "feature._lastHighlighter properly set after \"mouseout\""); 
+             "feature._lastHighlighter properly set after \"mouseout\"");
         t.eq(feature._prevHighlighter, undefined,
-             "feature._prevHighlighter properly set after \"mouseout\""); 
+             "feature._prevHighlighter properly set after \"mouseout\"");
 
         // click out of feature, feature is drawn with "default"
         _feature = null;
@@ -322,9 +322,9 @@
         t.eq(feature.renderIntent, "default",
              "feature drawn with expected render intent after \"clickout\"");
         t.eq(feature._lastHighlighter, undefined,
-             "feature._lastHighlighter properly set after \"clickout\""); 
+             "feature._lastHighlighter properly set after \"clickout\"");
         t.eq(feature._prevHighlighter, undefined,
-             "feature._prevHighlighter properly set after \"clickout\""); 
+             "feature._prevHighlighter properly set after \"clickout\"");
 
         // with selectStyle
 
@@ -373,6 +373,43 @@
         map.events.triggerEvent("click", evt);
     }
 
+    function test_setLayer(t) {
+        t.plan(5);
+        var map = new OpenLayers.Map("map");
+        var layer1 = new OpenLayers.Layer.Vector();
+        var layer2 = new OpenLayers.Layer.Vector();
+        var layer3 = new OpenLayers.Layer.Vector();
+        map.addLayer(layer1, layer2, layer3);
+        // initialize it with a single layer
+        var control = new OpenLayers.Control.SelectFeature(layer1);
+        map.addControl(control);
+        control.activate();
+        control.setLayer([layer2, layer3]);
+        t.eq(control.layer instanceof OpenLayers.Layer.Vector.RootContainer, true, "Root container created correctly on setLayer with multiple layers");
+        t.eq(control.active, true, "Control should be active still after using setLayer");
+        t.eq((control.handlers.feature.layer === control.layer), true, "Feature handler layer set correctly");
+        control.destroy();
+        // initialize with an array of layers
+        control = new OpenLayers.Control.SelectFeature([layer1, layer2]);
+        t.eq((control.layers !== null), true, "Control has a layers property");
+        control.setLayer(layer3);
+        t.eq((control.layers === null), true, "When using setLayer with a single layer, the layers property is removed if present before");
+        map.destroy();
+    }
+
+    function test_destroy(t) {
+        t.plan(1);
+        var map = new OpenLayers.Map("map");
+        var layer1 = new OpenLayers.Layer.Vector();
+        map.addLayer(layer1);
+        var control = new OpenLayers.Control.SelectFeature([layer1]);
+        map.addControl(control);
+        control.activate();
+        control.destroy();
+        t.eq(layer1.renderer.getRenderLayerId(), layer1.id, 
+            "Root container moved correctly when control is destroyed and layers was an array parameter");
+    }   
+   
     </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Control/TransformFeature.html (from rev 10919, trunk/openlayers/tests/Control/TransformFeature.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Control/TransformFeature.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Control/TransformFeature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,83 @@
+<html>
+<head>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(6);
+        var layer = "foo";
+        var control = new OpenLayers.Control.TransformFeature(layer);
+        
+        t.ok(control.layer == layer,
+             "constructor sets layer correctly");
+        t.ok(control.dragControl instanceof OpenLayers.Control.DragFeature,
+             "constructor sets the drag control correctly");
+        t.ok(control.box instanceof OpenLayers.Feature.Vector,
+             "box feature created");
+        t.eq(control.handles.length, 8, "8 handles created");
+        t.eq(control.rotationHandles.length, 4, "4 rotation handles created")
+        t.eq(typeof control.rotationHandleSymbolizer, "object",
+            "rotationHandleSymbolizer initialized");
+        control.destroy();
+    }
+
+    function test_destroy(t) {
+        t.plan(1);
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector();
+        map.addLayer(layer);
+        var control = new OpenLayers.Control.TransformFeature(layer);
+        control.dragControl.destroy = function() {
+            t.ok(true,
+                 "control.destroy calls destroy on drag control");
+        };
+        control.destroy();
+        map.destroy();
+    }
+    
+    function test_activate(t) {
+        t.plan(3);
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector();
+        map.addLayer(layer);
+        var control = new OpenLayers.Control.TransformFeature(layer);
+        map.addControl(control);
+        
+        t.ok(!control.dragControl.active,
+             "drag control is not active prior to activating control");
+        control.activate();
+        t.ok(control.dragControl.active,
+             "drag control is active after activating control");
+        t.ok(control.box.layer === layer, "box added to layer");
+
+        map.destroy();
+    }
+    
+    function test_setFeature(t) {
+        t.plan(4);
+        var map = new OpenLayers.Map("map", {allOverlays: true});
+        var layer = new OpenLayers.Layer.Vector();
+        var feature = new OpenLayers.Feature.Vector(
+            OpenLayers.Geometry.fromWKT("POLYGON((-1 -1, 1 -1, 1 1, -1 1))"));
+        layer.addFeatures([feature]);
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0, 0), 18);
+        var control = new OpenLayers.Control.TransformFeature(layer);
+        map.addControl(control);
+        control.setFeature(feature);
+        
+        t.ok(control.active, "control activated on setFeature");
+        t.ok(feature.geometry.getBounds().equals(control.box.geometry.getBounds()), "box positioned correctly");
+        t.geom_eq(control.handles[0].geometry, control.box.geometry.components[0], "handle positioned with box");
+        
+        var center = new OpenLayers.LonLat(1, 1);
+        control.box.move(center);
+        t.geom_eq(control.handles[0].geometry, control.box.geometry.components[0], "handle moved with box");
+    }
+
+    </script>
+</head>
+<body>
+    <div id="map" style="width: 400px; height: 250px;"/>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Control/WMSGetFeatureInfo.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control/WMSGetFeatureInfo.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control/WMSGetFeatureInfo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -5,7 +5,7 @@
 
     function test_initialize(t) {
         t.plan(5);
-        
+
         var options = {
             url: 'http://localhost/wms',
             layers: ["foo"],
@@ -17,14 +17,58 @@
         t.ok(control instanceof OpenLayers.Control.WMSGetFeatureInfo,
              "new OpenLayers.Control.WMSGetFeatureInfo returns an instance");
         t.eq(control.url, 'http://localhost/wms',
-             "constructor sets url correctly");        
+             "constructor sets url correctly");
         t.eq(control.layers, ["foo"],
              "constructor layers"
             );
         t.ok(control.format instanceof OpenLayers.Format.WMSGetFeatureInfo, "format created");
         t.eq(control.format.foo, "bar", "format options used")
     }
-    
+
+    function test_clickCallBack_option(t) {
+        t.plan(9);
+
+        var control;
+
+        control = new OpenLayers.Control.WMSGetFeatureInfo({
+            hover: true
+        });
+        t.ok(control.handler instanceof OpenLayers.Handler.Hover,
+             'constructor creates hover handler');
+        t.ok(control.handler.callbacks["move"] === control.cancelHover,
+             'constructor registers proper "move" callback in handler');
+        t.ok(control.handler.callbacks["pause"] === control.getInfoForHover,
+             'constructor registers proper "pause" callback in handler');
+
+        control = new OpenLayers.Control.WMSGetFeatureInfo();
+        t.ok(control.handler instanceof OpenLayers.Handler.Click,
+             'constructor creates click handler');
+        t.ok(control.handler.callbacks["click"] === control.getInfoForClick,
+             'constructor registers proper "click" callback in handler');
+
+        control = new OpenLayers.Control.WMSGetFeatureInfo({
+            clickCallback: "rightclick"
+        });
+        t.ok(control.handler.callbacks["rightclick"] === control.getInfoForClick,
+             'constructor registers proper "rightclick" callback in handler');
+
+        control = new OpenLayers.Control.WMSGetFeatureInfo({
+            clickCallback: "dblclick",
+            handlerOptions: {
+                click: {
+                    "single": false,
+                    "double": true
+                }
+            }
+        });
+        t.ok(control.handler.callbacks["dblclick"] === control.getInfoForClick,
+             'constructor registers proper "dblclick" callback in handler');
+        t.eq(control.handler["single"], false,
+             'constructor sets "single" to false in handler');
+        t.eq(control.handler["double"], true,
+             'constructor sets "double" to true in handler');
+     }
+
     function test_destroy(t) {
         t.plan(2);
         var map = new OpenLayers.Map("map");
@@ -42,15 +86,15 @@
         click.handler.deactivate = function() {
             t.ok(true,
                  "control.deactivate calls deactivate on click handler");
-        }
+        };
         hover.handler.deactivate = function() {
             t.ok(true,
                  "control.deactivate calls deactivate on hover handler");
-        }
+        };
         click.destroy();
         hover.destroy();
     }
-    
+
     function test_click(t) {
         t.plan(4);
         var map = new OpenLayers.Map('map');
@@ -59,18 +103,69 @@
         var control = new OpenLayers.Control.WMSGetFeatureInfo();
         map.addControl(control);
         control.activate();
-       
+
         control.request = function(position) {
             t.eq(position.x, 50,
                  "x position is as expected");
             t.eq(position.y, 50,
                  "y position is as expected");
-        }
+        };
 
         control.getInfoForClick({xy: {x: 50, y: 50}});
         control.getInfoForHover({xy: {x: 50, y: 50}});
     }
-   
+
+    function test_beforegetfeatureinfo_event(t) {
+        t.plan(2);
+        var map = new OpenLayers.Map('map');
+
+        var xy, mode;
+
+        // mock up active control
+        var control = new OpenLayers.Control.WMSGetFeatureInfo({
+            request: function(position) {},
+            eventListeners: {
+                beforegetfeatureinfo: function(evt) {
+                    t.eq(evt.xy, xy,
+                         "beforegetfeatureinfo listener gets " +
+                         "expected xy (" + mode + ")");
+                }
+            }
+        });
+        map.addControl(control);
+        control.activate();
+
+        // 1 test
+        mode = "click";
+        xy = {x: 50, y: 50};
+        control.getInfoForClick({xy: xy});
+
+        // 1 test
+        mode = "hover";
+        xy = {x: 70, y: 70};
+        control.getInfoForHover({xy: xy});
+    }
+
+    function test_nogetfeatureinfo_event(t) {
+        t.plan(1);
+        var map = new OpenLayers.Map('map');
+        // mock up active control
+        var control = new OpenLayers.Control.WMSGetFeatureInfo({
+            eventListeners: {
+                nogetfeatureinfo: function(evt) {
+                    t.ok((evt.type == "nogetfeatureinfo"), "nogetfeatureinfo listener gets called when there are no queryable layers");
+                }
+            }
+        });
+        map.addControl(control);
+        control.activate();
+
+        // 1 test
+        mode = "click";
+        xy = {x: 50, y: 50};
+        control.getInfoForClick({xy: xy});
+    }
+
     function test_activate(t) {
         t.plan(4);
         var map = new OpenLayers.Map("map");
@@ -125,20 +220,20 @@
             t.ok(true,
                  "control.deactivate calls deactivate on click handler");
             OpenLayers.Handler.Click.prototype.deactivate.apply(this, arguments);
-        }
+        };
         hover.handler.deactivate = function() {
             t.ok(true,
                  "control.deactivate calls deactivate on hover handler");
             OpenLayers.Handler.Hover.prototype.deactivate.apply(this, arguments);
-        }
+        };
         click.deactivate();
         hover.deactivate();
     }
 
-    // Verify that things work all right when we combine different types for the STYLES and LAYERS 
+    // Verify that things work all right when we combine different types for the STYLES and LAYERS
     // params in the WMS Layers involved
     function test_mixedParams(t) {
-        t.plan(2);
+        t.plan(3);
         var map = new OpenLayers.Map("map", {
             getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));}
             }
@@ -178,45 +273,51 @@
         click.activate();
         click.getInfoForClick({xy: {x: 50, y: 50}});
         OpenLayers.Request.GET = _request;
-        
+
         t.eq(
             log.options && log.options.url,
             "http://localhost/wms",
             "url from first layer used"
         );
         t.eq(
-            log.options && log.options.params.styles.join(","),
+            log.options && log.options.params.STYLES.join(","),
             "a,b,c,d,a,b,c,d,,,,,,,,",
             "Styles merged correctly"
-        );        
-        
+        );
+
+        t.eq(
+            log.options && log.options.params.FORMAT,
+            "image/jpeg",
+            "Required 'format' parameter included"
+ 	    );
+
     }
-    
+
     function test_urlMatches(t) {
-        
+
         t.plan(5);
 
         var control = new OpenLayers.Control.WMSGetFeatureInfo({
             url: "http://host/wms?one=1&two=2"
         });
-        
+
         t.ok(!control.urlMatches("foo"), "doesn't match garbage");
         t.ok(control.urlMatches("http://host:80/wms?two=2&one=1"), "matches equivalent url");
-        
+
         // give the control more urls to match from
         control.layerUrls = ["http://a.host/wms", "http://b.host/wms"];
-        
+
         t.ok(control.urlMatches("http://host:80/wms?two=2&one=1"), "still matches equivalent url");
         t.ok(control.urlMatches("http://a.host:80/wms"), "matches equivalent of first of layerUrls");
         t.ok(control.urlMatches("http://b.host:80/wms"), "matches equivalent of second of layerUrls");
 
     }
-    
+
     function test_layerUrls(t) {
 
         t.plan(4);
         var map = new OpenLayers.Map({
-            div: "map", 
+            div: "map",
             getExtent: function() {
                 return new OpenLayers.Bounds(-180,-90,180,90);
             }
@@ -231,45 +332,177 @@
         var c = new OpenLayers.Layer.WMS(
             null, ["http://c.mirror/wms", "http://d.mirror/wms"], {layers: "c"}
         );
-        
+
         var control = new OpenLayers.Control.WMSGetFeatureInfo({
             url: "http://host/wms",
             layers: [a, b, c]
         });
         map.addControl(control);
         control.activate();
-        
+
         // log calls to GET
         var log;
         var _request = OpenLayers.Request.GET;
         OpenLayers.Request.GET = function(options) {
             log.options = options;
         };
-        
+
         // control url doesn't match layer urls, no request issued
         log = {};
         control.getInfoForClick({xy: {x: 50, y: 50}});
         t.ok(!log.options, "no url match, no request issued");
-        
+
         // give control a list of urls to match
         log = {};
         control.layerUrls = ["http://a.mirror/wms", "http://b.mirror/wms"];
         control.getInfoForClick({xy: {x: 50, y: 50}});
         t.eq(log.options && log.options.url, "http://host/wms", "some match, request issued");
-        t.eq(log.options && log.options.params["query_layers"].join(","), "a,b", "selected layers queried");
-        
+        t.eq(log.options && log.options.params["QUERY_LAYERS"].join(","), "a,b", "selected layers queried");
+
         // show that a layer can be matched if it has a urls array itself (first needs to be matched)
         log = {};
         control.layerUrls = ["http://c.mirror/wms"];
         control.getInfoForClick({xy: {x: 50, y: 50}});
-        t.eq(log.options && log.options.params["query_layers"].join(","), "c", "layer with urls array can be queried");
-        
+        t.eq(log.options && log.options.params["QUERY_LAYERS"].join(","), "c", "layer with urls array can be queried");
+
         // clean up
         OpenLayers.Request.GET = _request;
         map.destroy();
 
     }
+    
+    function test_hover(t) {
+        
+        t.plan(2);
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            layers: [
+                new OpenLayers.Layer.WMS(null, "/dummywms", {layers: "one"})
+            ],
+            center: new OpenLayers.LonLat(0, 0),
+            zoom: 1
+        });
+        
+        var control = new OpenLayers.Control.WMSGetFeatureInfo({
+            hover: true
+        });
+        map.addControl(control);
+        control.activate();
+        
+        // mock up a mousemove
+        control.getInfoForHover({xy: new OpenLayers.Pixel(10, 10)});
+        t.ok(!!control.hoverRequest, "hoverRequest set");
+        
+        // confirm that request is canceled on next move
+        var called = 0;
+        control.hoverRequest.abort = function() {
+            ++called;
+        };
+        control.handler.px = null;
+        control.handler.mousemove({xy: new OpenLayers.Pixel(20, 20)});
+        t.eq(called, 1, "hover request aborted");
+        
+        map.destroy();
+        
+    }
 
+    function test_drillDown(t) {
+        t.plan(4);
+        var map = new OpenLayers.Map("map", {
+            getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));}
+            }
+        );
+
+        var a = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", {
+            layers: "a"
+        });
+
+        var b = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", {
+            layers: "c"
+        });
+
+        var c = new OpenLayers.Layer.WMS("dummy","http://myhost/wms", {
+            layers: "x"
+        });
+
+        map.addLayers([a, b, c]);
+
+        var click = new OpenLayers.Control.WMSGetFeatureInfo({
+            drillDown: true
+        });
+
+        map.addControl(click);
+
+        var count = 0;
+        var _request = OpenLayers.Request.GET;
+        OpenLayers.Request.GET = function(options) {
+            count++;
+            if (count == 1) {
+                t.eq(options.params["QUERY_LAYERS"].join(","), "a,c", "Layers should be grouped by service url");
+                t.eq(options.url, "http://localhost/wms", "Correct url used for first request");
+            } else if (count == 2) {
+                t.eq(options.url, "http://myhost/wms", "Correct url used for second request");
+            }
+        };
+        click.activate();
+        click.getInfoForClick({xy: {x: 50, y: 50}});
+        OpenLayers.Request.GET = _request;
+        t.eq(count, 2, "We expect 2 requests to go off");
+        map.destroy();
+    }
+
+    function test_GetFeatureInfo_WMS13(t) {
+        t.plan(4);
+        var map = new OpenLayers.Map("map", {
+            getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));}
+            }
+        );
+
+        var a = new OpenLayers.Layer.WMS(null, "http://localhost/wms", {
+            layers: "a",
+            version: "1.3.0"
+        });
+        map.addLayer(a);
+
+        var click = new OpenLayers.Control.WMSGetFeatureInfo({
+        });
+
+        map.addControl(click);
+        var log = {};
+        var _request = OpenLayers.Request.GET;
+        OpenLayers.Request.GET = function(options) {
+            log.options = options;
+        };
+        click.activate();
+        click.getInfoForClick({xy: {x: 50, y: 60}});
+        OpenLayers.Request.GET = _request;
+        t.eq(
+            log.options && log.options.params.CRS,
+            "EPSG:4326",
+            "Since it is WMS 1.3 use CRS parameter instead of SRS in the GetFeatureInfo request"
+        );
+
+        t.eq(
+            log.options && log.options.params.I,
+            50,
+            "Since it is WMS 1.3 use I parameter instead of X in the GetFeatureInfo request"
+        );
+
+        t.eq(
+            log.options && log.options.params.J,
+            60,
+            "Since it is WMS 1.3 use J parameter instead of Y in the GetFeatureInfo request"
+        );
+
+        t.eq(
+            log.options && log.options.params.BBOX,
+            "-90,-180,90,180",
+            "Since it is WMS 1.3 the BBOX should respect axis order"
+        );
+
+    }
+
     </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Control/WMTSGetFeatureInfo.html (from rev 10919, trunk/openlayers/tests/Control/WMTSGetFeatureInfo.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Control/WMTSGetFeatureInfo.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Control/WMTSGetFeatureInfo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,334 @@
+<html>
+<head>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(4);
+
+        var options = {
+            url: "http://localhost/wmts",
+            layers: ["foo"],
+            formatOptions: {
+                foo: "bar"
+            }
+        };
+        var control = new OpenLayers.Control.WMTSGetFeatureInfo(options);
+        t.ok(control instanceof OpenLayers.Control.WMTSGetFeatureInfo,
+             "new OpenLayers.Control.WMTSGetFeatureInfo returns an instance");
+        t.eq(control.layers, ["foo"],
+             "constructor layers"
+            );
+        t.ok(control.format instanceof OpenLayers.Format.WMSGetFeatureInfo, "format created");
+        t.eq(control.format.foo, "bar", "format options used")
+    }
+
+    function test_clickCallBack_option(t) {
+        t.plan(9);
+
+        var control;
+
+        control = new OpenLayers.Control.WMTSGetFeatureInfo({
+            hover: true
+        });
+        t.ok(control.handler instanceof OpenLayers.Handler.Hover,
+             'constructor creates hover handler');
+        t.ok(control.handler.callbacks["move"] === control.cancelHover,
+             'constructor registers proper "move" callback in handler');
+        t.ok(control.handler.callbacks["pause"] === control.getInfoForHover,
+             'constructor registers proper "pause" callback in handler');
+
+        control = new OpenLayers.Control.WMTSGetFeatureInfo();
+        t.ok(control.handler instanceof OpenLayers.Handler.Click,
+             'constructor creates click handler');
+        t.ok(control.handler.callbacks["click"] === control.getInfoForClick,
+             'constructor registers proper "click" callback in handler');
+
+        control = new OpenLayers.Control.WMTSGetFeatureInfo({
+            clickCallback: "rightclick"
+        });
+        t.ok(control.handler.callbacks["rightclick"] === control.getInfoForClick,
+             'constructor registers proper "rightclick" callback in handler');
+
+        control = new OpenLayers.Control.WMTSGetFeatureInfo({
+            clickCallback: "dblclick",
+            handlerOptions: {
+                click: {
+                    "single": false,
+                    "double": true
+                }
+            }
+        });
+        t.ok(control.handler.callbacks["dblclick"] === control.getInfoForClick,
+             'constructor registers proper "dblclick" callback in handler');
+        t.eq(control.handler["single"], false,
+             'constructor sets "single" to false in handler');
+        t.eq(control.handler["double"], true,
+             'constructor sets "double" to true in handler');
+     }
+
+    function test_destroy(t) {
+        t.plan(2);
+        var map = new OpenLayers.Map("map");
+        var click = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            layers: ["foo"]
+        });
+
+        var hover = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            layers: ["foo"],
+            hover: true
+        });
+
+        click.handler.deactivate = function() {
+            t.ok(true,
+                 "control.deactivate calls deactivate on click handler");
+        };
+        hover.handler.deactivate = function() {
+            t.ok(true,
+                 "control.deactivate calls deactivate on hover handler");
+        };
+        click.destroy();
+        hover.destroy();
+    }
+
+    function test_click(t) {
+        t.plan(4);
+        var map = new OpenLayers.Map('map');
+
+        // mock up active control
+        var control = new OpenLayers.Control.WMTSGetFeatureInfo();
+        map.addControl(control);
+        control.activate();
+
+        control.request = function(position) {
+            t.eq(position.x, 200,
+                 "x position is as expected");
+            t.eq(position.y, 125,
+                 "y position is as expected");
+        };
+
+        control.getInfoForClick({xy: {x: 200, y: 125}});
+        control.getInfoForHover({xy: {x: 200, y: 125}});
+    }
+
+    function test_beforegetfeatureinfo_event(t) {
+        t.plan(2);
+        var map = new OpenLayers.Map({
+            div: "map",
+            allOverlays: true,
+            layers: [
+                new OpenLayers.Layer.WMTS({
+                    name: "Test WMTS 1", 
+                    url: "/testwmts/",
+                    layer: "test1",
+                    style: "",
+                    matrixSet: "set-id",
+                    isBaseLayer: false
+                }),
+                new OpenLayers.Layer.WMTS({
+                    name: "Test WMTS 2", 
+                    url: "/testwmts/",
+                    layer: "test2",
+                    style: "",
+                    matrixSet: "set-id",
+                    isBaseLayer: false
+                })
+            ],
+            center: new OpenLayers.LonLat(0, 0),
+            zoom: 0
+        });
+
+        var log = [];
+
+        // test click
+        var click = new OpenLayers.Control.WMTSGetFeatureInfo({
+            drillDown: true,
+            eventListeners: {
+                beforegetfeatureinfo: function(evt) {
+                    log.push({xy: evt.xy});
+                }
+            }
+        });
+        map.addControl(click);
+        click.activate();
+        click.getInfoForClick({xy: {x: 200, y: 125}});
+        t.eq(log.length, 2, "click: beforegetfeatureinfo triggered twice");
+        log = [];
+        click.deactivate();
+
+        // test hover
+        var hover = new OpenLayers.Control.WMTSGetFeatureInfo({
+            hover: true,
+            eventListeners: {
+                beforegetfeatureinfo: function(evt) {
+                    log.push({xy: evt.xy});
+                }
+            }
+        });
+        map.addControl(hover);
+        hover.activate();
+        xy = {x: 70, y: 70};
+        hover.getInfoForHover({xy: {x: 70, y: 70}});
+        t.eq(log.length, 1, "hover: beforegetfeatureinfo triggered once");
+        log = [];
+        hover.deactivate();
+        
+        map.destroy();
+    }
+
+    function test_activate(t) {
+        t.plan(4);
+        var map = new OpenLayers.Map("map");
+        var click = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            layers: ['ns:type']
+        });
+        var hover = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            featureType: 'type',
+            featureNS: 'http://localhost/ns',
+            layers: 'ns:type',
+            hover: true
+        });
+        map.addControl(click);
+        map.addControl(hover);
+        t.ok(!click.handler.active,
+             "click handler is not active prior to activating control");
+        t.ok(!hover.handler.active,
+             "hover handler is not active prior to activating control");
+        click.activate();
+        hover.activate();
+        t.ok(click.handler.active,
+             "click handler is active after activating control");
+        t.ok(hover.handler.active,
+             "hover handler is active after activating control");
+    }
+
+    function test_deactivate(t) {
+        t.plan(2);
+        var map = new OpenLayers.Map("map");
+        var click = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            featureType: 'type',
+            featureNS: 'http://localhost/ns',
+            layers: 'ns:type'
+        });
+        var hover = new OpenLayers.Control.WMTSGetFeatureInfo({
+            url: 'http://localhost/wms',
+            featureType: 'type',
+            featureNS: 'http://localhost/ns',
+            layers: 'ns:type'
+        });
+        map.addControl(click);
+        map.addControl(hover);
+        click.activate();
+        hover.activate();
+
+        click.handler.deactivate = function() {
+            t.ok(true,
+                 "control.deactivate calls deactivate on click handler");
+            OpenLayers.Handler.Click.prototype.deactivate.apply(this, arguments);
+        };
+        hover.handler.deactivate = function() {
+            t.ok(true,
+                 "control.deactivate calls deactivate on hover handler");
+            OpenLayers.Handler.Hover.prototype.deactivate.apply(this, arguments);
+        };
+        click.deactivate();
+        hover.deactivate();
+    }
+
+    function test_getInfoForClick(t) {
+
+        t.plan(13);
+        var map = new OpenLayers.Map({
+            div: "map",
+            getExtent: function() {
+                return new OpenLayers.Bounds(-180,-90,180,90);
+            }
+        });
+
+        var a = new OpenLayers.Layer.WMTS({
+            url: "http://a.example.com/wmts",
+            layer: "a",
+            matrixSet: "bar",
+            style: "default"
+        });
+
+        var b = new OpenLayers.Layer.WMTS({
+            url: "http://b.example.com/wmts",
+            layer: "b",
+            matrixSet: "bar",
+            style: "default",
+            isBaseLayer: false
+        });
+
+        var c = new OpenLayers.Layer.WMTS({
+            url: ["http://c1.example.com/wmts", "http://c2.example.com"],
+            layer: "c",
+            matrixSet: "bar",
+            style: "default",
+            isBaseLayer: false
+        });
+        map.addLayers([a, b, c]);
+        map.zoomToMaxExtent();
+
+        var control = new OpenLayers.Control.WMTSGetFeatureInfo({
+            layers: [a, b, c]
+        });
+        map.addControl(control);
+        control.activate();
+
+        // log calls to GET
+        var log;
+        var _request = OpenLayers.Request.GET;
+        OpenLayers.Request.GET = function(options) {
+            log.push(options);
+        };
+
+        // query first layer (drillDown false)
+        log = [];
+        control.drillDown = false;
+        control.queryVisible = false;
+        control.getInfoForClick({xy: {x: 200, y: 125}});
+        t.eq(log.length, 1, "one requests issued");
+        t.eq(log[0].url, "http://c1.example.com/wmts", "{drillDown: false} correct url");
+        t.eq(log[0].params["LAYER"], "c", "{drillDown: false} correct layer parameter");
+
+        // query all layers
+        log = [];
+        control.drillDown = true;
+        control.queryVisible = false;
+        control.getInfoForClick({xy: {x: 200, y: 125}});
+        t.eq(log.length, 3, "three requests issued");
+        t.eq(log[0].url, "http://c1.example.com/wmts", "[c] correct url");
+        t.eq(log[0].params["LAYER"], "c", "[c] correct layer parameter");
+        t.eq(log[1].url, "http://b.example.com/wmts", "[b] correct url");
+        t.eq(log[1].params["LAYER"], "b", "[b] correct layer parameter");
+        t.eq(log[2].url, "http://a.example.com/wmts", "[a] correct url");
+        t.eq(log[2].params["LAYER"], "a", "[a] correct layer parameter");
+
+        // query only visible layers
+        log = [];
+        control.drillDown = true;
+        control.queryVisible = true;
+        b.setVisibility(false);
+        control.getInfoForClick({xy: {x: 200, y: 125}});
+        t.eq(log.length, 2, "two requests issued");
+        t.eq(log[0].url, "http://c1.example.com/wmts", "correct url for second visible layer");
+        t.eq(log[1].url, "http://a.example.com/wmts", "correct url for first visible layer");
+
+        // clean up
+        OpenLayers.Request.GET = _request;
+        map.destroy();
+
+    }
+
+    </script>
+</head>
+<body>
+    <div id="map" style="width: 400px; height: 250px;"/>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Control.html
===================================================================
--- sandbox/ahocevar/playground/tests/Control.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Control.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -72,7 +72,32 @@
         t.ok(control.map == null, "Control.map is null");
         t.ok(control.handler == null, "Control.handler is null");
     }
+    
+    function test_autoActivate(t) {
+        
+        t.plan(3);
+        
+        var control, map = new OpenLayers.Map("map");
 
+        // confirm that a control is not activated by default
+        control = new OpenLayers.Control();
+        map.addControl(control);
+        t.ok(!control.active, "control is not activated by default");
+        
+        // confirm that control is activated with autoActivate true
+        control = new OpenLayers.Control({autoActivate: true});
+        map.addControl(control);
+        t.ok(control.active, "control is activated with autoActivate true");
+       
+        // confirm that control is not activated with autoActivate false
+        control = new OpenLayers.Control({autoActivate: false});
+        map.addControl(control);
+        t.ok(!control.active, "control is not activated with autoActivate false");
+        
+        map.destroy();
+        
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Feature/Vector.html
===================================================================
--- sandbox/ahocevar/playground/tests/Feature/Vector.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Feature/Vector.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -58,6 +58,40 @@
         
     }
     
+    function test_Feature_getVisibility(t) {
+        t.plan(5);
+        var feature = new OpenLayers.Feature.Vector();
+        feature.layer = {
+            getVisibility: function() {return true}
+        };
+
+        t.ok(feature.getVisibility(),
+             "returns true in a not specific case");
+
+        feature.style = {display: 'none'};
+        t.eq(feature.getVisibility(), false,
+             "returns false when feature style display property is set to 'none'");
+
+        feature.style = null;
+        feature.layer.styleMap = {
+            createSymbolizer: function() {
+                return {display: 'none'}
+            }
+        }
+        t.eq(feature.getVisibility(), false,
+             "returns false when layer styleMap is configured so that the feature" +
+              "should not be displayed");
+
+        delete feature.layer.styleMap;
+        feature.layer.getVisibility = function() {return false}
+        t.eq(feature.getVisibility(), false,
+             "returns false when layer it belongs to is not visible");
+        
+        feature.layer = null;
+        t.eq(feature.getVisibility(), false,
+             "returns false when it doesn't belong to any layer");
+    }
+    
     function test_Feature_Vector_clone(t) {
         t.plan(6);
 

Modified: sandbox/ahocevar/playground/tests/Feature.html
===================================================================
--- sandbox/ahocevar/playground/tests/Feature.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Feature.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -43,7 +43,7 @@
         feature = new OpenLayers.Feature(layer, lonlat, data);
         popup = feature.createPopup(); 
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq(popup.contentDiv.style[prop], "auto", 'overflow on popup is correct');
     }    
     function test_Feature_createMarker (t) {

Modified: sandbox/ahocevar/playground/tests/Filter/Comparison.html
===================================================================
--- sandbox/ahocevar/playground/tests/Filter/Comparison.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Filter/Comparison.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -175,7 +175,117 @@
         }
         
     }
-    
+
+    function test_evaluate_feature(t) {
+        
+        var cases = [{
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.BETWEEN,
+                property: "area",
+                lowerBoundary: 1000,
+                upperBoundary: 4999
+            }),
+            context: new OpenLayers.Feature.Vector(null, {area: 999}),
+            expect: false
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.BETWEEN,
+                property: "area",
+                lowerBoundary: 1000,
+                upperBoundary: 4999
+            }),
+            context: new OpenLayers.Feature.Vector(null, {area: 1000}),
+            expect: true
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.BETWEEN,
+                property: "area",
+                lowerBoundary: 1000,
+                upperBoundary: 4999
+            }),
+            context: new OpenLayers.Feature.Vector(null, {area: 4999}),
+            expect: true
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.BETWEEN,
+                property: "area",
+                lowerBoundary: 1000,
+                upperBoundary: 4999
+            }),
+            context: new OpenLayers.Feature.Vector(null, {area: 5000}),
+            expect: false
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.BETWEEN,
+                property: "area",
+                lowerBoundary: 1000,
+                upperBoundary: 4999
+            }),
+            context: new OpenLayers.Feature.Vector(null, {area: 999}),
+            expect: false
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                property: "prop",
+                value: "Foo"
+            }),
+            context: new OpenLayers.Feature.Vector(null, {prop: "Foo"}),
+            expect: true
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                property: "prop",
+                value: "Foo"
+            }),
+            context: new OpenLayers.Feature.Vector(null, {prop: "foo"}),
+            expect: false
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                matchCase: true,
+                property: "prop",
+                value: "Foo"
+            }),
+            context: new OpenLayers.Feature.Vector(null, {prop: "foo"}),
+            expect: false
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+                property: "prop",
+                value: "foo"
+            }),
+            context: {prop: "FOO"},
+            expect: true
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+                matchCase: true,
+                property: "prop",
+                value: "foo"
+            }),
+            context: new OpenLayers.Feature.Vector(null, {prop: "FOO"}),
+            expect: true
+        }, {
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+                matchCase: false,
+                property: "prop",
+                value: "foo"
+            }),
+            context: new OpenLayers.Feature.Vector(null, {prop: "FOO"}),
+            expect: false
+        }];
+        
+        t.plan(cases.length);
+
+        var c;
+        for(var i=0; i<cases.length; ++i) {
+            c = cases[i];
+            t.eq(c.filter.evaluate(c.context), c.expect, "case " + i + ": " + c.filter.type);
+        }
+        
+    }
+        
     function test_clone(t) {
         
         t.plan(3);

Modified: sandbox/ahocevar/playground/tests/Filter/Logical.html
===================================================================
--- sandbox/ahocevar/playground/tests/Filter/Logical.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Filter/Logical.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -35,6 +35,75 @@
                 "feature evaluates to false correctly.");
     }
 
+    function test_evaluate_feature(t) {
+        t.plan(6);
+        
+        var feature = new OpenLayers.Feature.Vector(null, {
+            pop: 200,
+            name: "foo"
+        });
+        
+        var smallPop = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LESS_THAN,
+            property: "pop",
+            value: 120
+        });
+        
+        var bigPop = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.GREATER_THAN,
+            property: "pop",
+            value: 120
+        });
+        
+        var namedFoo = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.EQUAL_TO,
+            property: "name",
+            value: "foo"
+        });
+        
+        var filter;
+        
+        // test simple not
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.NOT,
+            filters: [smallPop]
+        });
+        t.eq(filter.evaluate(feature), true, "not smallPop");
+
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.NOT,
+            filters: [bigPop]
+        });
+        t.eq(filter.evaluate(feature), false, "not bigPop");
+
+        // test or
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.OR,
+            filters: [smallPop, namedFoo]
+        });
+        t.eq(filter.evaluate(feature), true, "smallPop or namedFoo");
+
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.OR,
+            filters: [bigPop, namedFoo]
+        });
+        t.eq(filter.evaluate(feature), true, "bigPop or namedFoo");
+
+        // test and
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: [smallPop, namedFoo]
+        });
+        t.eq(filter.evaluate(feature), false, "smallPop and namedFoo");
+
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: [bigPop, namedFoo]
+        });
+        t.eq(filter.evaluate(feature), true, "bigPop and namedFoo");
+
+    }
+
     function test_clone(t) {
         
         t.plan(2);

Modified: sandbox/ahocevar/playground/tests/Filter/Spatial.html
===================================================================
--- sandbox/ahocevar/playground/tests/Filter/Spatial.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Filter/Spatial.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -23,7 +23,7 @@
     }
     
     function test_evaluate(t) {
-        t.plan(4);
+        t.plan(8);
         
         var filer, feature, res, geom, bounds;
 
@@ -33,21 +33,25 @@
             value: bounds
         });
 
-        // 1 test
+        var not = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.NOT,
+            filters: [filter]
+        });
+
         feature = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.Point(2, 2));
         res = filter.evaluate(feature);
         t.eq(res, true,
             "evaluates returns correct value when feature intersects bounds");
-
-        // 1 test
+        t.eq(not.evaluate(feature), !res, "not bbox");
+        
         feature = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.Point(20, 20));
         res = filter.evaluate(feature);
         t.eq(res, false,
             "evaluates returns correct value when feature does not intersect bounds");
+        t.eq(not.evaluate(feature), !res, "not outside bbox");
 
-        // 1 test
         geom = bounds.toGeometry();
         feature = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.Point(2, 2));
@@ -58,8 +62,9 @@
         res = filter.evaluate(feature);
         t.eq(res, true,
             "evaluates returns correct value when feature intersects bounds");
+        not.filters = [filter];
+        t.eq(not.evaluate(feature), !res, "not intersection");
 
-        // 1 test
         geom = bounds.toGeometry();
         feature = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.Point(20, 20));
@@ -67,9 +72,13 @@
             type: OpenLayers.Filter.Spatial.INTERSECTS,
             value: geom
         });
+        not.filters = [filter];
         res = filter.evaluate(feature);
         t.eq(res, false,
             "evaluates returns correct value when feature does not intersect bounds");
+        t.eq(not.evaluate(feature), !res, "not non-intersection");
+
+
     }
     
     function test_clone(t) {

Copied: sandbox/ahocevar/playground/tests/Format/Atom.html (from rev 10919, trunk/openlayers/tests/Format/Atom.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/Atom.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/Atom.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,450 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(4); 
+        var options = {'foo': 'bar'}; 
+        var format = new OpenLayers.Format.Atom(options); 
+        t.ok(format instanceof OpenLayers.Format.Atom, 
+             "new OpenLayers.Format.GeoRSS returns object" ); 
+        t.eq(format.foo, "bar", "constructor sets options correctly"); 
+        t.eq(typeof format.read, "function", "format has a read function"); 
+        t.eq(typeof format.write, "function", "format has a write function"); 
+    }
+
+    /* Reading tests */
+
+    function test_reproject_null(t) { 
+        t.plan(1);
+        var parser = new OpenLayers.Format.Atom({'internalProjection':new OpenLayers.Projection("EPSG:4326"), 'externalProjection': new OpenLayers.Projection("EPSG:4326")});
+        var data = parser.read(
+          // begin document
+          '<feed xmlns="http://www.w3.org/2005/Atom">'  +
+          '<entry></entry>'                             +
+          '</feed>'
+          // end document
+          );
+        t.eq(
+          data.length, 1, 
+          "Parsing items with null geometry and reprojection doesn't fail"
+          );
+    }
+
+    // read entry 1: basic entry, no categories or persons
+    function test_readentry1(t) { 
+        t.plan(10);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
+          '  <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
+          '  <link href="http://example.com/blog/1" rel="alternate"/>'  +
+          '  <summary>An Atom testing entry</summary>'                  +
+          '  <title>Atom test</title>'                                  +
+          '  <updated>2009-06-02T10:00:00Z</updated>'                   +
+          '</entry>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        t.ok(fx instanceof OpenLayers.Feature.Vector, "Read feature");
+        t.eq(fx.geometry, null, "Geometry is null");
+        t.eq(
+            fx.fid, 
+            "urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed", 
+            "Read fid"
+            );
+        var attrib = fx.attributes;
+        t.eq(attrib.title, "Atom test", "Correct title attribute");
+        t.eq(
+            attrib.description, 
+            "An Atom testing entry", 
+            "Correct description attribute"
+            );
+        var atomAttrib = attrib.atom;
+        t.eq(
+            atomAttrib.links, 
+            [{href: "http://example.com/blog/1", rel: "alternate"}], 
+            "Correct links in atom namespace"
+            );
+        t.eq(
+            atomAttrib.summary, 
+            "An Atom testing entry", 
+            "Correct summary in atom namespace"
+            );
+        t.eq(
+            atomAttrib.title, 
+            "Atom test", 
+            "Correct title in atom namespace"
+            );
+        t.eq(
+            atomAttrib.updated, 
+            "2009-06-02T10:00:00Z", 
+            "Correct timestamp in atom namespace"
+            );
+    }
+
+    // read entry 2: with georss:where
+    function test_readentry2(t) { 
+        t.plan(5);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                   +
+          '  <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'      +
+          '  <georss:where xmlns:georss="http://www.georss.org/georss">'  +
+          '    <gml:Point xmlns:gml="http://www.opengis.net/gml">'        +
+          '      <gml:pos>45.68 -111.04</gml:pos>'                        +
+          '    </gml:Point>'                                              +
+          '  </georss:where>'                                             +
+          '</entry>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        t.ok(fx instanceof OpenLayers.Feature.Vector, "Read feature");
+        t.ok(fx.geometry instanceof OpenLayers.Geometry.Point, "Read geometry");
+        t.eq(fx.geometry.x, -111.04, "Read x");
+        t.eq(fx.geometry.y, 45.68, "Read y");
+    }
+
+    // read entry 3: with georss:point
+    function test_readentry3(t) { 
+        t.plan(5);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                   +
+          '  <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'      +
+          '  <georss:point xmlns:georss="http://www.georss.org/georss">45.68 -111.04</georss:point>'                                                   +
+          '</entry>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        t.ok(fx instanceof OpenLayers.Feature.Vector, "Read feature");
+        t.ok(fx.geometry instanceof OpenLayers.Geometry.Point, "Read geometry");
+        t.eq(fx.geometry.x, -111.04, "Read x");
+        t.eq(fx.geometry.y, 45.68, "Read y");
+    }
+
+    // read entry 4: basic entry, text content
+    function test_readentry4(t) { 
+        t.plan(3);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
+          '  <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
+          '  <link href="http://example.com/blog/1" rel="alternate"/>'  +
+          '  <summary>An Atom testing entry</summary>'                  +
+          '  <title>Atom test</title>'                                  +
+          '  <updated>2009-06-02T10:00:00Z</updated>'                   +
+          '  <content type="text">Blah, blah, blah</content>'           +
+          '</entry>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        var attrib = fx.attributes;
+        var atomAttrib = attrib.atom;
+        t.eq(
+            atomAttrib.content.type, 
+            "text", 
+            "Correct content.type in atom namespace"
+            );
+        t.eq(
+            atomAttrib.content.value, 
+            "Blah, blah, blah", 
+            "Correct content.value in atom namespace"
+            );
+    }
+
+    // read entry 5: basic entry, KML content
+    function test_readentry5(t) { 
+        t.plan(3);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
+          '  <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
+          '  <link href="http://example.com/blog/1" rel="alternate"/>'  +
+          '  <summary>An Atom testing entry</summary>'                  +
+          '  <title>Atom test</title>'                                  +
+          '  <updated>2009-06-02T10:00:00Z</updated>'                   +
+          '  <content type="application/vnd.google-earth.kml+xml"><kml xmlns="http://earth.google.com/kml/2.0"><Folder><name>A folder</name><description>It\'s a folder</description></Folder></kml></content>'                          +
+          '</entry>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        var attrib = fx.attributes;
+        var atomAttrib = attrib.atom;
+        t.eq(
+            atomAttrib.content.type, 
+            "application/vnd.google-earth.kml+xml", 
+            "Correct content.type in atom namespace"
+            );
+        var node = atomAttrib.content.value;
+        var name = node.localName || node.nodeName.split(":").pop();
+        t.eq(
+            name, 
+            "kml", 
+            "Correct content.value in atom namespace"
+            );
+    }
+    
+    // read feed 1
+    function test_readfeed1(t) { 
+        t.plan(2);
+        var parser = new OpenLayers.Format.Atom();
+        var data = parser.read(
+          // begin document
+          '<feed xmlns="http://www.w3.org/2005/Atom">'                  +
+          '  <entry>'                                                   +
+          '    <id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'  +
+          '  </entry>'                                                  +
+          '</feed>'
+          // end document
+          );
+        t.ok(data instanceof Array, "Read features");
+        var fx = data[0];
+        t.ok(fx instanceof OpenLayers.Feature.Vector, "Read feature");
+    }
+    
+    /* Writing tests */
+  
+    // write entry 1: null geometry, no attributes
+    function test_writeentry1(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">' +
+          '<id>1</id>'                                  +
+          '<title>untitled</title>'                     +
+          '</entry>',
+          // end document 
+          'Writes an entry doc with id, no attributes'
+          );
+    }
+
+    // write entry 2: null geometry, well-known attributes
+    function test_writeentry2(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature"});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">' +
+          '<id>1</id>'                                  +
+          '<summary>A testing feature</summary>'        +
+          '<title>Test</title>'                         +
+          '</entry>',
+          // end document
+          'Writes an entry doc with id, well-known attributes'
+          );
+    }
+
+    // write entry 3: null geometry, Atom constructs to override 
+    // well-known attributes
+    function test_writeentry3(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature", atom: {title: "Atom test", summary: "An Atom testing feature", updated: "2009-06-02T10:00:00Z"}});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">' +
+          '<id>1</id>'                                  +
+          '<summary>An Atom testing feature</summary>'  +
+          '<title>Atom test</title>'                    +
+          '<updated>2009-06-02T10:00:00Z</updated>'     +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs overriding well-known atts'
+          );
+    }
+
+    // write entry 4: Atom categories
+    function test_writeentry4(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature", atom: {title: "Atom test", summary: "An Atom testing feature", updated: "2009-06-02T10:00:00Z", categories: [{term: "blog", scheme: "http://example.com/terms", label: "A blog post"}]}});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">' +
+          '<category term="blog" scheme="http://example.com/terms" label="A blog post"/>'                                           +
+          '<id>1</id>'                                  +
+          '<summary>An Atom testing feature</summary>'  +
+          '<title>Atom test</title>'                    +
+          '<updated>2009-06-02T10:00:00Z</updated>'     +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs and categories'
+          );
+    }
+
+    // write entry 5: Atom authors, contributors
+    function test_writeentry5(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature", atom: {title: "Atom test", summary: "An Atom testing feature", updated: "2009-06-02T10:00:00Z", authors: [{name: "John Doe", uri: "http://example.com/people/jdoe", email: "jdoe at example.com"}], contributors: [{name: "Pikov Andropov", uri: "http://example.com/people/pandropov", email: "pandropov at example.com"}]}});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">' +
+          '<author>'                                    +
+          '  <name>John Doe</name>'                     +
+          '  <uri>http://example.com/people/jdoe</uri>' +
+          '  <email>jdoe at example.com</email>'           +
+          '</author>'                                   +
+          '<contributor>'                               +
+          '  <name>Pikov Andropov</name>'               +
+          '  <uri>http://example.com/people/pandropov</uri>' +
+          '  <email>pandropov at example.com</email>'      +
+          '</contributor>'                              +
+          '<id>1</id>'                                  +
+          '<summary>An Atom testing feature</summary>'  +
+          '<title>Atom test</title>'                    +
+          '<updated>2009-06-02T10:00:00Z</updated>'     +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs and persons'
+          );
+    }
+
+    // write entry 6: Atom links
+    function test_writeentry6(t) { 
+        t.plan(1);
+        
+        // Feature attributes in Atom namespace
+        var atomAttrib = {
+              title: "Atom test", 
+              summary: "An Atom testing feature", 
+              updated: "2009-06-02T10:00:00Z", 
+              links: [
+                { href: "http://example.com/blog/1", rel: "alternate" }
+                ]
+              };
+        var fx = new OpenLayers.Feature.Vector(null, {atom: atomAttrib});
+        fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';
+        
+        var writer = new OpenLayers.Format.Atom();
+        var data = writer.write(fx);
+        
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'               +
+          '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
+          '<link href="http://example.com/blog/1" rel="alternate"/>'  +
+          '<summary>An Atom testing feature</summary>'                +
+          '<title>Atom test</title>'                                  +
+          '<updated>2009-06-02T10:00:00Z</updated>'                   +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs and links'
+          );
+    }
+
+    // write out point -- just enough to see that we're getting the
+    // georss:where element with a Point. We'll trust GML.v3 to get the
+    // details right.
+    function test_writepoint(t) { 
+        t.plan(1);
+
+        var point = new OpenLayers.Geometry.Point(-111.04, 45.68);  
+        var fx = new OpenLayers.Feature.Vector(point, {});
+        fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';
+        
+        var writer = new OpenLayers.Format.Atom();
+        var data = writer.write(fx);
+        
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
+          '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'      +
+          '<title>untitled</title>'                                     +
+          '<georss:where xmlns:georss="http://www.georss.org/georss">'  +
+          '  <gml:Point xmlns:gml="http://www.opengis.net/gml">'        +
+          '    <gml:pos>45.68 -111.04</gml:pos>'                        +
+          '  </gml:Point>'                                              +
+          '</georss:where>'                                             +
+          '</entry>',
+          // end document
+          'Writes an entry doc with a point location'
+          );
+    }
+
+    // write entry 7: text type content
+    function test_writeentry7(t) { 
+        t.plan(1);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature", atom: {title: "Atom test", summary: "An Atom testing feature", updated: "2009-06-02T10:00:00Z", content: {type: "text", value: "Blah, blah, blah"}}});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'     +
+          '<content type="text">Blah, blah, blah</content>' +
+          '<id>1</id>'                                      +
+          '<summary>An Atom testing feature</summary>'      +
+          '<title>Atom test</title>'                        +
+          '<updated>2009-06-02T10:00:00Z</updated>'         +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs overriding well-known atts'
+          );
+    }
+
+    // write entry 8: +xml type content
+    function test_writeentry8(t) { 
+        t.plan(1);
+        var kml = new OpenLayers.Format.KML();
+        kml.foldersName = "A folder";
+        kml.foldersDesc = "It's a folder";
+        var kmlDoc = kml.createElementNS(kml.kmlns, "kml");
+        var kmlFolder = kml.createFolderXML();
+        kmlDoc.appendChild(kmlFolder);
+        var writer = new OpenLayers.Format.Atom();
+        var feature = new OpenLayers.Feature.Vector(null, {title: "Test", description: "A testing feature", atom: {title: "Atom test", summary: "An Atom testing feature", updated: "2009-06-02T10:00:00Z", content: {type: "application/vnd.google-earth.kml+xml", value: kmlDoc}}});
+        feature.fid = '1';
+        var data = writer.write(feature);
+        t.xml_eq(
+          data,
+          // begin document
+          '<entry xmlns="http://www.w3.org/2005/Atom">'     +
+          '<content type="application/vnd.google-earth.kml+xml"><kml xmlns="http://earth.google.com/kml/2.0"><Folder><name>A folder</name><description>It\'s a folder</description></Folder></kml></content>' +
+          '<id>1</id>'                                      +
+          '<summary>An Atom testing feature</summary>'      +
+          '<title>Atom test</title>'                        +
+          '<updated>2009-06-02T10:00:00Z</updated>'         +
+          '</entry>',
+          // end document
+          'Writes an entry doc with Atom constructs overriding well-known atts'
+          );
+    }
+    </script> 
+</head> 
+<body> 
+</body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html
===================================================================
--- trunk/openlayers/tests/Format/CSWGetDomain/v2_0_2.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,56 +0,0 @@
-<html> 
-<head> 
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script src="v2_0_2.js"></script>
-    <script type="text/javascript">
-
-    var format = new OpenLayers.Format.CSWGetDomain();
-    
-    function test_write(t) {
-
-        t.plan(1);
-
-        var options = {
-            PropertyName: "type"
-        };
-
-        var result = format.write(options);
-
-        t.eq(result, csw_request, "check value returned by format " +
-                "CSWGetDomain: write method");
-
-    }
-
-    
-    function test_read(t) {
-        
-        t.plan(9);
-        
-        var obj = format.read(csw_response);
-        
-        var domainValues = obj.DomainValues;
-        // test getRecordsResponse object
-        t.ok(domainValues, "object contains DomainValues property");
-
-        // test DomainValues
-        t.eq(domainValues.length, 1, "object contains 1 object in DomainValues");
-        var domainValue = domainValues[0];
-        t.eq(domainValue.type, "csw:Record", "check value for attribute type");
-        t.eq(domainValue.PropertyName, "type", "check value for element PropertyName");
-        t.ok(domainValue.ListOfValues, "object contains ListOfValues property");
-
-        // test ListOfValues
-        t.eq(domainValue.ListOfValues.length, 2, "object contains 2 objects " +
-                "in ListOfValues");
-        var val = domainValue.ListOfValues[0];
-        t.ok(val.Value, "object contains Value property");
-        t.eq(val.Value.my_attr, "my_value", "check value for attribute my_attr");
-        t.eq(val.Value.value, "dataset", "check value for element Value");
-        
-    }
-    
-    </script> 
-</head> 
-<body>
-</body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html (from rev 10919, trunk/openlayers/tests/Format/CSWGetDomain/v2_0_2.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,56 @@
+<html> 
+<head> 
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script src="v2_0_2.js"></script>
+    <script type="text/javascript">
+
+    var format = new OpenLayers.Format.CSWGetDomain();
+    
+    function test_write(t) {
+
+        t.plan(1);
+
+        var options = {
+            PropertyName: "type"
+        };
+
+        var result = format.write(options);
+
+        t.eq(result, csw_request, "check value returned by format " +
+                "CSWGetDomain: write method");
+
+    }
+
+    
+    function test_read(t) {
+        
+        t.plan(9);
+        
+        var obj = format.read(csw_response);
+        
+        var domainValues = obj.DomainValues;
+        // test getRecordsResponse object
+        t.ok(domainValues, "object contains DomainValues property");
+
+        // test DomainValues
+        t.eq(domainValues.length, 1, "object contains 1 object in DomainValues");
+        var domainValue = domainValues[0];
+        t.eq(domainValue.type, "csw:Record", "check value for attribute type");
+        t.eq(domainValue.PropertyName, "type", "check value for element PropertyName");
+        t.ok(domainValue.ListOfValues, "object contains ListOfValues property");
+
+        // test ListOfValues
+        t.eq(domainValue.ListOfValues.length, 2, "object contains 2 objects " +
+                "in ListOfValues");
+        var val = domainValue.ListOfValues[0];
+        t.ok(val.Value, "object contains Value property");
+        t.eq(val.Value.my_attr, "my_value", "check value for attribute my_attr");
+        t.eq(val.Value.value, "dataset", "check value for element Value");
+        
+    }
+    
+    </script> 
+</head> 
+<body>
+</body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js
===================================================================
--- trunk/openlayers/tests/Format/CSWGetDomain/v2_0_2.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,18 +0,0 @@
-var csw_request = 
-'<csw:GetDomain xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" service="CSW" version="2.0.2">' +
-  '<csw:PropertyName>type</csw:PropertyName>' +
-'</csw:GetDomain>';
-
-var csw_response = 
-'<?xml version="1.0" encoding="UTF-8"?>' +
-'<csw:GetDomainResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">' +
-  '<csw:DomainValues type="csw:Record">' +
-    '<csw:PropertyName>type</csw:PropertyName>' +
-    '<csw:ListOfValues>' +
-      '<csw:Value my_attr="my_value">dataset</csw:Value>' +
-      '<csw:Value>service</csw:Value>' +
-    '</csw:ListOfValues>' +
-  '</csw:DomainValues>' +
-'</csw:GetDomainResponse>'
-;
-

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js (from rev 10919, trunk/openlayers/tests/Format/CSWGetDomain/v2_0_2.js)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetDomain/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,18 @@
+var csw_request = 
+'<csw:GetDomain xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" service="CSW" version="2.0.2">' +
+  '<csw:PropertyName>type</csw:PropertyName>' +
+'</csw:GetDomain>';
+
+var csw_response = 
+'<?xml version="1.0" encoding="UTF-8"?>' +
+'<csw:GetDomainResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">' +
+  '<csw:DomainValues type="csw:Record">' +
+    '<csw:PropertyName>type</csw:PropertyName>' +
+    '<csw:ListOfValues>' +
+      '<csw:Value my_attr="my_value">dataset</csw:Value>' +
+      '<csw:Value>service</csw:Value>' +
+    '</csw:ListOfValues>' +
+  '</csw:DomainValues>' +
+'</csw:GetDomainResponse>'
+;
+

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetDomain.html (from rev 10919, trunk/openlayers/tests/Format/CSWGetDomain.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetDomain.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetDomain.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,23 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(2);
+
+        var format = new OpenLayers.Format.CSWGetDomain();
+        t.ok(format instanceof OpenLayers.Format.CSWGetDomain.v2_0_2, "constructor returns instance with default versioned format");
+
+        format = new OpenLayers.Format.CSWGetDomain({
+            version: "2.0.2"
+        });
+        t.ok(format instanceof OpenLayers.Format.CSWGetDomain.v2_0_2, "constructor returns instance with custom versioned format");
+    }
+
+  </script>
+</head>
+<body>
+<div id="map" style="width:512px; height:256px"> </div>
+</body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html
===================================================================
--- trunk/openlayers/tests/Format/CSWGetRecords/v2_0_2.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,81 +0,0 @@
-<html> 
-<head> 
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script src="v2_0_2.js"></script>
-    <script type="text/javascript">
-
-    var format = new OpenLayers.Format.CSWGetRecords();
-    
-    function test_write(t) {
-
-        t.plan(1);
-
-        var filter =  new OpenLayers.Filter.Comparison({
-            type: OpenLayers.Filter.Comparison.LIKE,
-            property: "my_prop",
-            value: "my_prop_value"
-        });
-
-        var options = {
-            "resultType": "results",
-            "startPosition": "10",
-            "maxRecords": "20",
-            "Query": {
-                "ElementSetName": {
-                    "value": "brief"
-                },
-                "Constraint": {
-                    "version": "1.1.0",
-                    "Filter": filter
-                }
-            }
-        };
-
-        var result = format.write(options);
-
-        t.eq(result, csw_request, "check value returned by format " +
-                "CSWGetRecords: write method");
-
-    }
-
-    
-    function test_read(t) {
-        
-        t.plan(14);
-        
-        var obj = format.read(csw_response);
-        
-        var searchStatus = obj.SearchStatus;
-        var searchResults = obj.SearchResults;
-        var records = obj.records;
-        // test getRecordsResponse object
-        t.ok(searchStatus, "object contains SearchStatus property");
-        t.ok(searchResults, "object contains SearchResults property");
-        t.ok(records, "object contains records property");
-
-        // test SearchResults attributes
-        t.eq(searchResults.numberOfRecordsMatched, 10, "check value for SearchResults.numberOfRecordsMatched");
-        t.eq(searchResults.numberOfRecordsReturned, 2, "check value for SearchResults.numberOfRecordsReturned");
-        t.eq(searchResults.elementSet, "brief", "check value for SearchResults.elementSet");
-        t.eq(searchResults.nextRecord, 3, "check value for SearchResults.nextRecord");
-
-        // test records
-        t.eq(records.length, 2, "object contains 10 records");
-        var testRecord = records[0];
-        t.eq(testRecord.type, "BriefRecord", "check value for record.type");
-        t.eq(testRecord.title, [{value:"Sample title"}], "check value for record.title");
-
-        //test bbox
-        t.eq(testRecord.BoundingBox.length, 2, "object contains 2 BoundingBoxes");
-        var bbox = testRecord.BoundingBox[0];
-        t.ok(bbox, "object contains BoundingBox properties");
-        t.eq(bbox.crs, "::Lambert Azimuthal Projection", "check value for BoundingBox.crs");
-        t.eq(bbox.value, [156, -3, 37, 83], "check value for record.BoundingBox");
-        
-    }
-    
-    </script> 
-</head> 
-<body>
-</body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html (from rev 10919, trunk/openlayers/tests/Format/CSWGetRecords/v2_0_2.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,81 @@
+<html> 
+<head> 
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script src="v2_0_2.js"></script>
+    <script type="text/javascript">
+
+    var format = new OpenLayers.Format.CSWGetRecords();
+    
+    function test_write(t) {
+
+        t.plan(1);
+
+        var filter =  new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LIKE,
+            property: "my_prop",
+            value: "my_prop_value"
+        });
+
+        var options = {
+            "resultType": "results",
+            "startPosition": "10",
+            "maxRecords": "20",
+            "Query": {
+                "ElementSetName": {
+                    "value": "brief"
+                },
+                "Constraint": {
+                    "version": "1.1.0",
+                    "Filter": filter
+                }
+            }
+        };
+
+        var result = format.write(options);
+
+        t.eq(result, csw_request, "check value returned by format " +
+                "CSWGetRecords: write method");
+
+    }
+
+    
+    function test_read(t) {
+        
+        t.plan(14);
+        
+        var obj = format.read(csw_response);
+        
+        var searchStatus = obj.SearchStatus;
+        var searchResults = obj.SearchResults;
+        var records = obj.records;
+        // test getRecordsResponse object
+        t.ok(searchStatus, "object contains SearchStatus property");
+        t.ok(searchResults, "object contains SearchResults property");
+        t.ok(records, "object contains records property");
+
+        // test SearchResults attributes
+        t.eq(searchResults.numberOfRecordsMatched, 10, "check value for SearchResults.numberOfRecordsMatched");
+        t.eq(searchResults.numberOfRecordsReturned, 2, "check value for SearchResults.numberOfRecordsReturned");
+        t.eq(searchResults.elementSet, "brief", "check value for SearchResults.elementSet");
+        t.eq(searchResults.nextRecord, 3, "check value for SearchResults.nextRecord");
+
+        // test records
+        t.eq(records.length, 2, "object contains 10 records");
+        var testRecord = records[0];
+        t.eq(testRecord.type, "BriefRecord", "check value for record.type");
+        t.eq(testRecord.title, [{value:"Sample title"}], "check value for record.title");
+
+        //test bbox
+        t.eq(testRecord.BoundingBox.length, 2, "object contains 2 BoundingBoxes");
+        var bbox = testRecord.BoundingBox[0];
+        t.ok(bbox, "object contains BoundingBox properties");
+        t.eq(bbox.crs, "::Lambert Azimuthal Projection", "check value for BoundingBox.crs");
+        t.eq(bbox.value, [156, -3, 37, 83], "check value for record.BoundingBox");
+        
+    }
+    
+    </script> 
+</head> 
+<body>
+</body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js
===================================================================
--- trunk/openlayers/tests/Format/CSWGetRecords/v2_0_2.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,44 +0,0 @@
-var csw_request = 
-'<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" service="CSW" version="2.0.2" resultType="results" startPosition="10" maxRecords="20">' +
-  '<csw:Query typeNames="csw:Record">' +
-    '<csw:ElementSetName>brief</csw:ElementSetName>' +
-    '<csw:Constraint version="1.1.0">' +
-      '<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
-        '<ogc:PropertyIsLike wildCard="*" singleChar="." escapeChar="!">' +
-          '<ogc:PropertyName>my_prop</ogc:PropertyName>' +
-          '<ogc:Literal>my_prop_value</ogc:Literal>' +
-        '</ogc:PropertyIsLike>' +
-      '</ogc:Filter>' +
-    '</csw:Constraint>' +
-  '</csw:Query>' +
-'</csw:GetRecords>';
-
-var csw_response = 
-'<?xml version="1.0" encoding="UTF-8"?>' +
-'<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">' +
-  '<csw:SearchStatus timestamp="2009-06-08T12:03:34" />' +
-  '<csw:SearchResults numberOfRecordsMatched="10" numberOfRecordsReturned="2" elementSet="brief" nextRecord="3">' +
-    '<csw:BriefRecord xmlns:geonet="http://www.fao.org/geonetwork" xmlns:ows="http://www.opengis.net/ows" xmlns:dc="http://purl.org/dc/elements/1.1/">' +
-      '<dc:identifier>895ac38b-7aef-4a21-b593-b35a6fc7bba9</dc:identifier>' +
-      '<dc:title>Sample title</dc:title>' +
-      '<ows:BoundingBox crs="::Lambert Azimuthal Projection">' +
-        '<ows:LowerCorner>156 -3</ows:LowerCorner>' +
-        '<ows:UpperCorner>37 83</ows:UpperCorner>' +
-      '</ows:BoundingBox>' +
-      '<ows:BoundingBox crs="::WGS 1984">' +
-        '<ows:LowerCorner>51.1 -34.6</ows:LowerCorner>' +
-        '<ows:UpperCorner>-17.3 38.2</ows:UpperCorner>' +
-      '</ows:BoundingBox>' +
-    '</csw:BriefRecord>' +
-    '<csw:BriefRecord xmlns:geonet="http://www.fao.org/geonetwork" xmlns:ows="http://www.opengis.net/ows" xmlns:dc="http://purl.org/dc/elements/1.1/">' +
-      '<dc:identifier>8a7245c3-8546-42de-8e6f-8fb8b5fd1bc3</dc:identifier>' +
-      '<dc:title>Second record : sample title</dc:title>' +
-      '<ows:BoundingBox crs="::WGS 1984">' +
-        '<ows:LowerCorner>51.1 -34.6</ows:LowerCorner>' +
-        '<ows:UpperCorner>-17.3 38.2</ows:UpperCorner>' +
-      '</ows:BoundingBox>' +
-    '</csw:BriefRecord>' +
-  '</csw:SearchResults>' +
-'</csw:GetRecordsResponse>'
-;
-

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js (from rev 10919, trunk/openlayers/tests/Format/CSWGetRecords/v2_0_2.js)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetRecords/v2_0_2.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,44 @@
+var csw_request = 
+'<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" service="CSW" version="2.0.2" resultType="results" startPosition="10" maxRecords="20">' +
+  '<csw:Query typeNames="csw:Record">' +
+    '<csw:ElementSetName>brief</csw:ElementSetName>' +
+    '<csw:Constraint version="1.1.0">' +
+      '<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
+        '<ogc:PropertyIsLike wildCard="*" singleChar="." escapeChar="!">' +
+          '<ogc:PropertyName>my_prop</ogc:PropertyName>' +
+          '<ogc:Literal>my_prop_value</ogc:Literal>' +
+        '</ogc:PropertyIsLike>' +
+      '</ogc:Filter>' +
+    '</csw:Constraint>' +
+  '</csw:Query>' +
+'</csw:GetRecords>';
+
+var csw_response = 
+'<?xml version="1.0" encoding="UTF-8"?>' +
+'<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">' +
+  '<csw:SearchStatus timestamp="2009-06-08T12:03:34" />' +
+  '<csw:SearchResults numberOfRecordsMatched="10" numberOfRecordsReturned="2" elementSet="brief" nextRecord="3">' +
+    '<csw:BriefRecord xmlns:geonet="http://www.fao.org/geonetwork" xmlns:ows="http://www.opengis.net/ows" xmlns:dc="http://purl.org/dc/elements/1.1/">' +
+      '<dc:identifier>895ac38b-7aef-4a21-b593-b35a6fc7bba9</dc:identifier>' +
+      '<dc:title>Sample title</dc:title>' +
+      '<ows:BoundingBox crs="::Lambert Azimuthal Projection">' +
+        '<ows:LowerCorner>156 -3</ows:LowerCorner>' +
+        '<ows:UpperCorner>37 83</ows:UpperCorner>' +
+      '</ows:BoundingBox>' +
+      '<ows:BoundingBox crs="::WGS 1984">' +
+        '<ows:LowerCorner>51.1 -34.6</ows:LowerCorner>' +
+        '<ows:UpperCorner>-17.3 38.2</ows:UpperCorner>' +
+      '</ows:BoundingBox>' +
+    '</csw:BriefRecord>' +
+    '<csw:BriefRecord xmlns:geonet="http://www.fao.org/geonetwork" xmlns:ows="http://www.opengis.net/ows" xmlns:dc="http://purl.org/dc/elements/1.1/">' +
+      '<dc:identifier>8a7245c3-8546-42de-8e6f-8fb8b5fd1bc3</dc:identifier>' +
+      '<dc:title>Second record : sample title</dc:title>' +
+      '<ows:BoundingBox crs="::WGS 1984">' +
+        '<ows:LowerCorner>51.1 -34.6</ows:LowerCorner>' +
+        '<ows:UpperCorner>-17.3 38.2</ows:UpperCorner>' +
+      '</ows:BoundingBox>' +
+    '</csw:BriefRecord>' +
+  '</csw:SearchResults>' +
+'</csw:GetRecordsResponse>'
+;
+

Copied: sandbox/ahocevar/playground/tests/Format/CSWGetRecords.html (from rev 10919, trunk/openlayers/tests/Format/CSWGetRecords.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/CSWGetRecords.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/CSWGetRecords.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,23 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+
+    function test_initialize(t) {
+        t.plan(2);
+
+        var format = new OpenLayers.Format.CSWGetRecords();
+        t.ok(format instanceof OpenLayers.Format.CSWGetRecords.v2_0_2, "constructor returns instance with default versioned format");
+
+        format = new OpenLayers.Format.CSWGetRecords({
+            version: "2.0.2"
+        });
+        t.ok(format instanceof OpenLayers.Format.CSWGetRecords.v2_0_2, "constructor returns instance with custom versioned format");
+    }
+
+  </script>
+</head>
+<body>
+<div id="map" style="width:512px; height:256px"> </div>
+</body>
+</html>


Property changes on: sandbox/ahocevar/playground/tests/Format/Filter
___________________________________________________________________
Modified: svn:mergeinfo
   - 
   + /trunk/openlayers/tests/Format/Filter:7565-7650,7733-10919

Modified: sandbox/ahocevar/playground/tests/Format/GML/v2.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/GML/v2.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/GML/v2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -188,12 +188,13 @@
             xy: false
         });
         var features = format.read(doc.documentElement);
-        var geom = features[0].geometry;
-        t.ok(geom.bounds instanceof OpenLayers.Bounds, "geometry given a bounds");
-        t.eq(geom.bounds.left.toFixed(2), "-91.52", "bounds left correct");
-        t.eq(geom.bounds.bottom.toFixed(2), "36.99", "bounds bottom correct");
-        t.eq(geom.bounds.right.toFixed(2), "-87.51", "bounds right correct");
-        t.eq(geom.bounds.top.toFixed(2), "42.51", "bounds top correct");
+        var bounds = features[0].bounds;
+
+        t.ok(bounds instanceof OpenLayers.Bounds, "feature given a bounds");
+        t.eq(bounds.left.toFixed(2), "-91.52", "bounds left correct");
+        t.eq(bounds.bottom.toFixed(2), "36.99", "bounds bottom correct");
+        t.eq(bounds.right.toFixed(2), "-87.51", "bounds right correct");
+        t.eq(bounds.top.toFixed(2), "42.51", "bounds top correct");
     }
     
     function test_write(t) {
@@ -229,6 +230,24 @@
         t.eq(features[0].namespace, "http://mapserver.gis.umn.edu/mapserver", "Namespace is set correctly on feature");
     }
 
+    function test_noGeom(t) {
+        t.plan(7);
+        var doc = readXML("v2/nogeom.xml");
+        var format = new OpenLayers.Format.GML.v2({
+            featureType: "DEPARTEMENT",
+            featureNS: "http://server.fr/geoserver/loc"
+        });
+        var features = format.read(doc.documentElement);
+        t.eq(features.length, 2, "Expected 2 features from GML with no geom");
+        var feature = features[0];
+        t.ok(feature.geometry == null, "feature 0 has no geometry");
+        var bounds = feature.bounds;
+        t.ok(bounds && (bounds instanceof OpenLayers.Bounds), "feature 0 has been assigned bounds");
+        t.eq(bounds.left, 209565, "bounds left correct");
+        t.eq(bounds.bottom, 6785323, "bounds bottom correct");
+        t.eq(bounds.right, 337568, "bounds right correct");
+        t.eq(bounds.top, 6885985, "bounds top correct");
+    }
    </script>
 </head>
 <body>
@@ -642,5 +661,8 @@
 <div id="v2/multipletypenames.xml"><!--
 <?xml version='1.0' encoding="ISO-8859-1" ?><wfs:FeatureCollection   xmlns:rws="http://mapserver.gis.umn.edu/mapserver"   xmlns:wfs="http://www.opengis.net/wfs"   xmlns:gml="http://www.opengis.net/gml"   xmlns:ogc="http://www.opengis.net/ogc"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd                        http://mapserver.gis.umn.edu/mapserver http://intranet.rijkswaterstaat.nl/services/geoservices/kerngisnat_utre?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=VKUNSTWERK,LKUNSTWERK,PKUNSTWERK&amp;OUTPUTFORMAT=XMLSCHEMA">      <gml:boundedBy>      	<gml:Box srsName="EPSG:28992">      		<gml:coordinates>134503.789000,455332.337000 135149.909000,455893.926000</gml:coordinates>      	</gml:Box>      </gml:boundedBy>    <gml:featureMember>      <rws:VKUNSTWERK fid="VKUNSTWERK.16">        <gml:boundedBy>        	<gml:Box srsName="EPSG:28992
 ">        		<gml:coordinates>134949.571000,455438.845000 134978.799000,455471.762000</gml:coordinates>        	</gml:Box>        </gml:boundedBy>        <rws:geometry>        <gml:MultiPolygon srsName="EPSG:28992">        <gml:polygonMember>          <gml:Polygon>            <gml:outerBoundaryIs>              <gml:LinearRing>                <gml:coordinates>134974.191000,455471.587000 134973.974000,455471.762000 134973.558000,455471.248000 134973.579000,455471.230000 134963.143000,455458.768000 134962.787000,455458.653000 134960.514000,455456.003000 134960.440000,455455.539000 134950.207000,455443.320000 134950.158000,455443.360000 134949.571000,455442.638000 134949.810000,455442.462000 134951.417000,455441.223000 134951.435000,455441.209000 134954.158000,455439.108000 134954.507000,455438.845000 134955.000000,455439.420000 134954.954000,455439.458000 134965.046000,455451.520000 134965.568000,455451.606000 134968.159000,455454.642000 134968.120000,455455.195000 134978.294000
 ,455467.355000 134978.330000,455467.326000 134978.799000,455467.881000 134978.598000,455468.042000 134975.885000,455470.224000 134974.191000,455471.587000 </gml:coordinates>              </gml:LinearRing>            </gml:outerBoundaryIs>            <gml:innerBoundaryIs>              <gml:LinearRing>                <gml:coordinates>134960.590000,455455.163000 134963.589000,455458.755000 134973.756000,455470.929000 134973.836000,455471.019000 134974.216000,455471.445000 134975.807000,455470.163000 134978.485000,455468.005000 134978.077000,455467.534000 134978.015000,455467.462000 134967.969000,455455.479000 134964.782000,455451.678000 134954.705000,455439.660000 134954.622000,455439.561000 134954.271000,455439.152000 134951.498000,455441.284000 134949.973000,455442.456000 134950.452000,455443.023000 134950.501000,455443.081000 134960.590000,455455.163000 </gml:coordinates>              </gml:LinearRing>            </gml:innerBoundaryIs>          </gml:Polygon>        </gml:po
 lygonMember>        </gml:MultiPolygon>        </rws:geometry>        <rws:OBJECTID>16</rws:OBJECTID>        <rws:OBJECTSUBCATEGORIE>31</rws:OBJECTSUBCATEGORIE>      </rws:VKUNSTWERK>    </gml:featureMember>    <gml:featureMember>      <rws:LKUNSTWERK fid="LKUNSTWERK.14">        <gml:boundedBy>        	<gml:Box srsName="EPSG:28992">        		<gml:coordinates>135080.966000,455332.337000 135149.909000,455390.384000</gml:coordinates>        	</gml:Box>        </gml:boundedBy>        <rws:geometry>        <gml:MultiLineString srsName="EPSG:28992">          <gml:lineStringMember>            <gml:LineString>              <gml:coordinates>135080.966000,455390.384000 135096.654000,455377.009000 135109.082000,455366.755000 135122.769000,455355.276000 135141.565000,455339.633000 135149.909000,455332.337000 </gml:coordinates>            </gml:LineString>          </gml:lineStringMember>        </gml:MultiLineString>        </rws:geometry>        <rws:OBJECTID>14</rws:OBJECTID>        <
 rws:OBJECTSUBCATEGORIE>30</rws:OBJECTSUBCATEGORIE>      </rws:LKUNSTWERK>    </gml:featureMember>    <gml:featureMember>      <rws:PKUNSTWERK fid="PKUNSTWERK.29">        <gml:boundedBy>        	<gml:Box srsName="EPSG:28992">        		<gml:coordinates>134832.017000,455596.187000 134832.017000,455596.187000</gml:coordinates>        	</gml:Box>        </gml:boundedBy>        <rws:geometry>        <gml:MultiPoint srsName="EPSG:28992">          <gml:pointMember>            <gml:Point>              <gml:coordinates>134832.017000,455596.187000</gml:coordinates>            </gml:Point>          </gml:pointMember>        </gml:MultiPoint>        </rws:geometry>        <rws:OBJECTID>29</rws:OBJECTID>        <rws:OBJECTSUBCATEGORIE>30</rws:OBJECTSUBCATEGORIE>      </rws:PKUNSTWERK>    </gml:featureMember></wfs:FeatureCollection>
 --></div>
+<div id="v2/nogeom.xml"><!--
+<?xml version="1.0" encoding="UTF-8"?><wfs:FeatureCollection xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:loc="http://server.fr/geoserver/loc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://server.fr:80/geoserver/schemas/wfs/1.0.0/WFS-basic.xsd http://server.fr/geoserver/loc http://server.fr:80/geoserver/wfs?service=WFS&amp;version=1.0.0&amp;request=DescribeFeatureType&amp;typeName=loc:DEPARTEMENT"><gml:boundedBy><gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#2154"><gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">199373,6704170 337568,6885985</gml:coordinates></gml:Box></gml:boundedBy><gml:featureMember><loc:DEPARTEMENT fid="DEPARTEMENT.1"><gml:boundedBy><gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#2154"><gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">2
 09565,6785323 337568,6885985</gml:coordinates></gml:Box></gml:boundedBy><loc:NOM_DEPT>COTES-D'ARMOR</loc:NOM_DEPT></loc:DEPARTEMENT></gml:featureMember><gml:featureMember><loc:DEPARTEMENT fid="DEPARTEMENT.3"><gml:boundedBy><gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#2154"><gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">199373,6704170 323518,6807542</gml:coordinates></gml:Box></gml:boundedBy><loc:NOM_DEPT>MORBIHAN</loc:NOM_DEPT></loc:DEPARTEMENT></gml:featureMember></wfs:FeatureCollection>
+--></div>
 </body>
 </html>

Modified: sandbox/ahocevar/playground/tests/Format/GML/v3.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/GML/v3.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/GML/v3.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -179,13 +179,13 @@
             xy: false
         });
         var features = format.read(doc.documentElement);
-        
-        var geom = features[0].geometry;
-        t.ok(geom.bounds instanceof OpenLayers.Bounds, "geometry given a bounds");
-        t.eq(geom.bounds.left.toFixed(2), "-91.52", "bounds left correct");
-        t.eq(geom.bounds.bottom.toFixed(2), "36.99", "bounds bottom correct");
-        t.eq(geom.bounds.right.toFixed(2), "-87.51", "bounds right correct");
-        t.eq(geom.bounds.top.toFixed(2), "42.51", "bounds top correct");
+        var bounds = features[0].bounds;
+
+        t.ok(bounds instanceof OpenLayers.Bounds, "feature given a bounds");
+        t.eq(bounds.left.toFixed(2), "-91.52", "bounds left correct");
+        t.eq(bounds.bottom.toFixed(2), "36.99", "bounds bottom correct");
+        t.eq(bounds.right.toFixed(2), "-87.51", "bounds right correct");
+        t.eq(bounds.top.toFixed(2), "42.51", "bounds top correct");
     }
 
     function test_read(t) {
@@ -244,7 +244,25 @@
         t.eq(attr.foo, undefined, "bogus attribute is undefined");
         t.eq(attr.empty, "", "empty attribute value is empty string");
     }
+    
+    function test_repeatedName(t) {
+        // test that if an attribute name matches the featureType, all goes well
+        t.plan(2);
+        var doc = readXML("v3/repeated-name.xml");
+        var format = new OpenLayers.Format.GML.v3({
+            featureType: "zoning",
+            featureNS: "http://opengeo.org/#medford",
+            geometryName: "the_geom",
+            xy: false
+        });
+        var features = format.read(doc.documentElement);
+        
+        t.eq(features.length, 1, "read one feature");
+        var atts = features[0].attributes;
+        t.eq(atts.zoning, "I-L", "correct zoning attribute on zoning feature type");
 
+    }
+
     function test_write(t) {
         t.plan(1);
         var doc = readXML("v3/topp-states-gml.xml");
@@ -724,5 +742,49 @@
     </gml:lineStringMember>
 </gml:MultiLineString>
 --></div>
+<div id="v3/repeated-name.xml"><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<wfs:FeatureCollection numberOfFeatures="1" timeStamp="2010-01-29T15:10:38.921-07:00"
+        xsi:schemaLocation="http://medford.opengeo.org http://localhost:8080/geoserver/wfs?service=WFS&amp;version=1.1.0&amp;request=DescribeFeatureType&amp;typeName=medford%3Azoning http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.1.0/wfs.xsd"
+        xmlns:ogc="http://www.opengis.net/ogc"
+        xmlns:wfs="http://www.opengis.net/wfs"
+        xmlns:medford="http://opengeo.org/#medford"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:ows="http://www.opengis.net/ows"
+        xmlns:gml="http://www.opengis.net/gml"
+        xmlns:xlink="http://www.w3.org/1999/xlink">
+    <gml:featureMembers>
+        <medford:zoning gml:id="zoning.1">
+            <medford:the_geom>
+                <gml:MultiSurface srsName="urn:x-ogc:def:crs:EPSG:4326">
+                    <gml:surfaceMember>
+                        <gml:Polygon>
+                            <gml:exterior>
+                                <gml:LinearRing>
+                                    <gml:posList>42.397027571297585 -122.88465674265922 42.39702893980587 -122.88509730796012 42.397029086785146 -122.88511582432085 42.39702379767053 -122.88528111596624 42.39748517484964 -122.88529300380065 42.39748473847452 -122.88509914138723 42.39748482219041 -122.8849959517568 42.397485082635576 -122.8846741899541 42.3974853307826 -122.88436529392652 42.39702663751206 -122.88435664014142 42.397027571297585 -122.88465674265922</gml:posList>
+                                </gml:LinearRing>
+                            </gml:exterior>
+                        </gml:Polygon>
+                    </gml:surfaceMember>
+                </gml:MultiSurface>
+            </medford:the_geom>
+            <medford:objectid>1</medford:objectid>
+            <medford:cityzone>YES</medford:cityzone>
+            <medford:zoning>I-L</medford:zoning>
+            <medford:revdate>2004-04-12T00:00:00-06:00</medford:revdate>
+            <medford:finord></medford:finord>
+            <medford:filenum></medford:filenum>
+            <medford:acres>0.95741118624</medford:acres>
+            <medford:misc></medford:misc>
+            <medford:shape_leng>835.705330224</medford:shape_leng>
+            <medford:perimeter>835.705330224</medford:perimeter>
+            <medford:area>41704.8312728</medford:area>
+            <medford:shape_le_1>835.705330224</medford:shape_le_1>
+            <medford:shape_area>41704.8312728</medford:shape_area>
+            <medford:hectares>0.38745056079</medford:hectares>
+        </medford:zoning>
+    </gml:featureMembers>
+</wfs:FeatureCollection>
+-->
 </body>
 </html>

Modified: sandbox/ahocevar/playground/tests/Format/GML.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/GML.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/GML.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -338,7 +338,49 @@
         var expect = '<gml:Box xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="." cs="," ts=" ">-180,-90 180,90</gml:coordinates></gml:Box>';
         t.xml_eq(output, expect, "[xy true] Bounds correctly written as gml:Box");
     }
+    
+    function test_parseFeatureBox(t) {
+        t.plan(8); 
+        var parser = new OpenLayers.Format.GML();
+        var xmlparser = new OpenLayers.Format.XML();
 
+        var data = xmlparser.read(test_box[0]);
+        var feature = parser.parseFeature(data);
+        t.ok(feature.bounds instanceof OpenLayers.Bounds, 
+             "got bounds object for feature.bounds when with boundedBy Box, without geometry");
+        t.eq(feature.geometry, null, 'geometry is null for a feature with boundedBy Box, but no geometry');
+
+        var data = xmlparser.read(test_box[1]);
+        feature = parser.parseFeature(data);
+        t.eq(feature.bounds, null,
+             "feature is null when without boundedBy Box, with Box geometry");
+        t.ok(feature.geometry instanceof OpenLayers.Geometry.Polygon,
+             "got polygon object for feature.geometry when without boundedBy Box, with Box geometry");
+
+        data = xmlparser.read(test_box[2]);
+        feature = parser.parseFeature(data);
+        t.eq(feature.bounds, null, 
+             "feature.bounds is null when without boundedBy Box, without geometry");
+        t.eq(feature.geometry, null, 'geometry is null when without boundedBy Box, without geometry');
+
+        data = xmlparser.read(test_box[3]);
+        feature = parser.parseFeature(data);
+        t.ok(feature.bounds instanceof OpenLayers.Bounds, 
+             "got bounds object for feature.bounds when with boundedBy Box, with Box geometry");
+        t.ok(feature.geometry instanceof OpenLayers.Geometry.Polygon,
+             "got polygon object for feature.geometry when with boundedBy Box, with Box geometry");
+    }
+    
+    var test_box = [
+        // with boundedBy Box, without geometry
+        '<Sentiers_littoraux_feature><gml:boundedBy xmlns:gml="http://www.opengis.net/gml"><gml:Box srsName="EPSG:2154"><gml:coordinates>143564.081753,6817901.121957 144209.641321,6819104.781451</gml:coordinates></gml:Box></gml:boundedBy><DEPARTEMENT>Finistère</DEPARTEMENT></Sentiers_littoraux_feature>',
+        // without boundedBy Box, with Box geometry
+        '<Sentiers_littoraux_feature><msGeometry><gml:Box srsName="EPSG:2154" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates>143564.081753,6817901.121957 144209.641321,6819104.781451</gml:coordinates></gml:Box></msGeometry><DEPARTEMENT>Finistère</DEPARTEMENT></Sentiers_littoraux_feature>',
+        // without boundedBy, without geometry
+        '<Sentiers_littoraux_feature><DEPARTEMENT>Finistère</DEPARTEMENT></Sentiers_littoraux_feature>',
+        // with boundedBy Box, with Box geometry
+        '<Sentiers_littoraux_feature><msGeometry><gml:Box srsName="EPSG:2154" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates>143564.081753,6817901.121957 144209.641321,6819104.781451</gml:coordinates></gml:Box></msGeometry><gml:boundedBy xmlns:gml="http://www.opengis.net/gml"><gml:Box srsName="EPSG:2154"><gml:coordinates>143564.081753,6817901.121957 144209.641321,6819104.781451</gml:coordinates></gml:Box></gml:boundedBy><DEPARTEMENT>Finistère</DEPARTEMENT></Sentiers_littoraux_feature>'];
+
     var test_content = ['<?xml version="1.0" encoding="utf-8" ?>\n<ogr:FeatureCollection\n     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n     xsi:schemaLocation="http://ogr.maptools.org/ testoutput.xsd"\n     xmlns:ogr="http://ogr.maptools.org/"\n     xmlns:gml="http://www.opengis.net/gml">\n  <gml:boundedBy>\n    <gml:Box>\n      <gml:coord><gml:X>-1254041.389711702</gml:X><gml:Y>250906.9515983529</gml:Y></gml:coord>\n      <gml:coord><gml:X>-634517.1199908922</gml:X><gml:Y>762236.2940800377</gml:Y></gml:coord>\n    </gml:Box>\n  </gml:boundedBy>                    \n  <gml:featureMember>\n    <ogr:states fid="F0">\n      <ogr:geometryProperty><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-634517.11999089224,691849.77929356066,0 -653761.64509297756,471181.53429472551,0 -673343.60852865304,250906.9515983529,0 -1088825.734430399,299284.85108220269,0 -1254041.3897117018,324729.27754874947,0 -1235750.4212498858,434167.33911316615,0 -1190777.780
 3201093,704392.96327195223,0 -1181607.835811228,762236.29408003774,0 -634517.11999089224,691849.77929356066,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>\n      <ogr:NAME>WY</ogr:NAME>\n    <ogr:EMPTYATTR/><ogr:LONGNAME><![CDATA[Wyoming]]></ogr:LONGNAME>\n    </ogr:states>\n  </gml:featureMember>\n</ogr:FeatureCollection>\n',
  '<wfs:FeatureCollection' + 
  '   xmlns:fs="http://example.com/featureserver"' + 
@@ -365,11 +407,11 @@
  '</gml:featureMember> ' +
  ' <gml:featureMember><fs:scribble fid="8">    <fs:geometry>        <gml:Point><gml:coordinates>-81.38671875,27.0703125</gml:coordinates></gml:Point>         </fs:geometry> ' +
  '        <fs:down>south</fs:down><fs:title>Florida</fs:title>        </fs:scribble></gml:featureMember>' + 
- '</wfs:FeatureCollection>' 
+ '</wfs:FeatureCollection>'
  ];
    
     var shell_start = '<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:features xmlns:feature="http://mapserver.gis.umn.edu/mapserver" fid="221"><feature:geometry>'; 
-    if (OpenLayers.Util.getBrowserName() == "opera") {
+    if (OpenLayers.BROWSER_NAME == "opera") {
         shell_start = '<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:features fid="221" xmlns:feature="http://mapserver.gis.umn.edu/mapserver"><feature:geometry>'; 
     }    
     var shell_end = '</feature:geometry></feature:features></gml:featureMember></wfs:FeatureCollection>';

Modified: sandbox/ahocevar/playground/tests/Format/GPX.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/GPX.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/GPX.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -6,7 +6,7 @@
     var gpx_data = '<?xml version="1.0" encoding="ISO-8859-1"?><gpx version="1.1" creator="Memory-Map 5.1.3.715 http://www.memory-map.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"><wpt lat="51.3697845627" lon="-0.1853562259"><name>Mark</name><sym><![CDATA[Flag]]></sym><type><![CDATA[Marks]]></type></wpt><rte><name><![CDATA[Route8]]></name><type><![CDATA[Route]]></type><rtept lat="51.3761803674" lon="-0.1829991904"><name><![CDATA[WP0801]]></name><sym><![CDATA[Dot]]></sym><type><![CDATA[Waypoints]]></type></rtept><rtept lat="51.3697894659" lon="-0.1758887005"><name><![CDATA[WP0802]]></name><sym><![CDATA[Dot]]></sym><type><![CDATA[Waypoints]]></type></rtept><rtept lat="51.3639790884" lon="-0.1833202965"><name><![CDATA[WP0803]]></name><sym><![CDATA[Dot]]></sym><type><![CDATA[Waypoints]]></type></rtept><rtept lat="51.3567607069" l
 on="-0.1751119509"><name><![CDATA[WP0804]]></name><sym><![CDATA[Dot]]></sym><type><![CDATA[Waypoints]]></type></rtept></rte><trk><name><![CDATA[Track]]></name><type><![CDATA[Track]]></type><trkseg><trkpt lat="51.3768216433" lon="-0.1721292044"></trkpt><trkpt lat="51.3708337670" lon="-0.1649230916"></trkpt><trkpt lat="51.3644368725" lon="-0.1736741378"></trkpt><trkpt lat="51.3576354272" lon="-0.1662595250"></trkpt></trkseg></trk></gpx>';
     
     function test_Format_GPX_constructor(t) { 
-        t.plan(4); 
+        t.plan(5); 
          
         var options = {'foo': 'bar'}; 
         var format = new OpenLayers.Format.GPX(options); 
@@ -15,6 +15,8 @@
         t.eq(format.foo, "bar", "constructor sets options correctly"); 
         t.eq(typeof format.read, "function", "format has a read function"); 
         t.eq(typeof format.write, "function", "format has a write function"); 
+        t.eq(format.externalProjection.getCode(), "EPSG:4326", 
+             "default external projection is EPSG:4326"); 
     }
     function test_Format_GPX_read(t) {
         t.plan(4);

Modified: sandbox/ahocevar/playground/tests/Format/GeoJSON.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/GeoJSON.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/GeoJSON.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -409,6 +409,18 @@
         t.eq(data[0].bounds.top, 74.0, "read top left bound is correct");
     }
 
+    function test_Format_GeoJSON_point_extradims(t) { 
+        t.plan(3);
+        var point_feature_3d = '{"geometry": {"type": "Point", "coordinates": [94.21875, 72.94921875, 0.0]}, "type": "Feature", "id": 573, "properties": {"strokeColor": "blue", "title": "Feature 5", "author": "Your Name Here"}}';
+        p = new OpenLayers.Format.GeoJSON({"ignoreExtraDims": true});
+        data = p.read(point_feature_3d);
+        t.eq(data[0].fid, 573, "Fid is correct on point feature"); 
+        t.eq(data[0].geometry.x, 94.21875, 'Reading point feature gives correct x');
+        data = p.read(point_feature_3d, "Feature");
+        t.eq(data.fid, 573, 'Reading point feature with type gives feature instead of array of features ');
+    }
+
+
     </script> 
 </head> 
 <body> 

Modified: sandbox/ahocevar/playground/tests/Format/KML.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/KML.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/KML.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -5,11 +5,13 @@
 
     var test_content = '<kml xmlns="http://earth.google.com/kml/2.0"><Folder><name>OpenLayers export</name><description>Vector geometries from OpenLayers</description><Placemark id="KML.Polygon"><name>OpenLayers.Feature.Vector_344</name><description>A KLM Polygon</description><Polygon><outerBoundaryIs><LinearRing><coordinates>5.001370157823406,49.26855713824488 8.214706453896161,49.630662409673505 8.397385910100951,48.45172350357396 5.001370157823406,49.26855713824488</coordinates></LinearRing></outerBoundaryIs></Polygon></Placemark><Placemark id="KML.LineString"><name>OpenLayers.Feature.Vector_402</name><description>A KML LineString</description><LineString><coordinates>5.838523393080493,49.74814616928052 5.787079558782349,48.410795432216574 8.91427702008381,49.28932499608202</coordinates></LineString></Placemark><Placemark id="KML.Point"><name>OpenLayers.Feature.Vector_451</name><description>A KML Point</description><Point><coordinates>6.985073041685488,49.8682250149058</c
 oordinates></Point></Placemark><Placemark id="KML.MultiGeometry"><name>SF Marina Harbor Master</name><description>KML MultiGeometry</description><MultiGeometry><LineString><coordinates>-122.4425587930444,37.80666418607323 -122.4428379594768,37.80663578323093</coordinates></LineString><LineString><coordinates>-122.4425509770566,37.80662588061205 -122.4428340530617,37.8065999493009</coordinates></LineString></MultiGeometry></Placemark></Folder></kml>';
     var test_style = '<kml xmlns="http://earth.google.com/kml/2.0"> <Placemark>    <Style> <LineStyle> <color>870000ff</color> <width>10</width> </LineStyle> </Style>  <LineString> <coordinates> -112,36 -113,37 </coordinates> </LineString> </Placemark></kml>';
-    var test_style_fill = '<kml xmlns="http://earth.google.com/kml/2.0"> <Placemark>    <Style> <PolyStyle> <fill>0</fill> <color>870000ff</color> <width>10</width> </PolyStyle> </Style>  <LineString> <coordinates> -112,36 -113,37 </coordinates> </LineString> </Placemark></kml>';
+    var test_style_fill = '<kml xmlns="http://earth.google.com/kml/2.0"> <Placemark>    <Style> <PolyStyle> <fill>1</fill> <color>870000ff</color> <width>10</width> </PolyStyle> </Style>  <LineString> <coordinates> -112,36 -113,37 </coordinates> </LineString> </Placemark><Placemark>    <Style> <PolyStyle> <fill>0</fill> <color>870000ff</color> <width>10</width> </PolyStyle> </Style>  <LineString> <coordinates> -112,36 -113,37 </coordinates> </LineString> </Placemark></kml>';
+    var test_style_outline = '<kml xmlns="http://earth.google.com/kml/2.0"> <Placemark>    <Style> <PolyStyle> <outline>0</outline> <color>870000ff</color> <width>10</width> </PolyStyle> </Style>  <LineString> <coordinates> -112,36 -113,37 </coordinates> </LineString> </Placemark></kml>';
+    var test_style_font = '<kml xmlns="http://earth.google.com/kml/2.0"> <Placemark><Style><LabelStyle><color>870000ff</color><scale>1.5</scale></LabelStyle></Style><LineString><coordinates> -112,36 -113,37 </coordinates></LineString></Placemark></kml>';
     var test_nl = '<kml xmlns="http://earth.google.com/kml/2.2"> <Document> <NetworkLink> <Link> <href>http://maker.geocommons.com/maps/1717/overlays/0</href> </Link> </NetworkLink> </Document></kml>';
 
     function test_Format_KML_constructor(t) { 
-        t.plan(4); 
+        t.plan(5); 
          
         var options = {'foo': 'bar'}; 
         var format = new OpenLayers.Format.KML(options); 
@@ -18,6 +20,8 @@
         t.eq(format.foo, "bar", "constructor sets options correctly"); 
         t.eq(typeof format.read, "function", "format has a read function"); 
         t.eq(typeof format.write, "function", "format has a write function");
+        t.eq(format.externalProjection.getCode(), "EPSG:4326", 
+             "default external projection is EPSG:4326"); 
     }
 
     function test_Format_KML_read(t) {
@@ -33,7 +37,7 @@
 
     function test_Format_KML_readCdataAttributes_20(t) {
         t.plan(2);
-        var cdata = '<kml xmlns="http://earth.google.com/kml/2.0"><Document><Placemark><name><![CDATA[Pezinok]]></name><description><![CDATA[Full of text.]]></description><styleUrl>#rel1.0</styleUrl><Point> <coordinates>17.266666, 48.283333</coordinates></Point></Placemark></Document></kml>';
+        var cdata = '<kml xmlns="http://earth.google.com/kml/2.0"><Document><Placemark><name><![CDATA[Pezinok]]> </name><description><![CDATA[Full of text.]]></description><styleUrl>#rel1.0</styleUrl><Point> <coordinates>17.266666, 48.283333</coordinates></Point></Placemark></Document></kml>';
         var features = (new OpenLayers.Format.KML()).read(cdata);
         t.eq(features[0].attributes.description, "Full of text.", "Description attribute in cdata read correctly");
         t.eq(features[0].attributes.name, "Pezinok", "title attribute in cdata read correctly");
@@ -63,9 +67,9 @@
         t.plan(1);
         var kmlExpected = this.test_content;
         var options = {
-            folderName: "OpenLayers export",
+            foldersName: "OpenLayers export",
             foldersDesc: "Vector geometries from OpenLayers"
-        }
+        };
 
         var format = new OpenLayers.Format.KML(options);
         var features = format.read(kmlExpected);
@@ -73,6 +77,20 @@
         var kmlOut = kmlOut.replace(/<\?[^>]*\?>/, ''); // Remove XML Prolog
         t.eq(kmlOut, kmlExpected, "correctly writes an KML doc string");
     }
+
+    function test_Format_KML_write_noNameDesc(t) {
+        t.plan(1);
+        var format = new OpenLayers.Format.KML({
+            foldersName: null,
+            foldersDesc: null
+        });
+        var geom = new OpenLayers.Geometry.Point(0, 0)
+        var feature = new OpenLayers.Feature.Vector(geom);
+        feature.id = 42;
+        var kmlOut = format.write(feature);
+        var expected = '<kml xmlns="http://earth.google.com/kml/2.0"><Folder><Placemark><name>42</name><description>No description available</description><Point><coordinates>0,0</coordinates></Point></Placemark></Folder></kml>'
+        t.eq(kmlOut, expected, "null foldersName or foldersDesc don't create elements");
+    }
     
     function test_Format_KML_write_multis(t) {
         /**
@@ -138,11 +156,25 @@
     function test_Format_KML_extractStyleFill(t) {
         t.plan(2);
         var f = new OpenLayers.Format.KML({extractStyles: true});
-        var features = f.read(test_style);    
-        t.eq(features[0].style.fillColor, "#ff0000", "default fill is set");        
         var features = f.read(test_style_fill);    
-        t.eq(features[0].style.fillColor, "none", "KML Feature has none fill");        
+        t.eq(features[0].style.fillColor, "#ff0000", "default fill is set");  
+        t.eq(features[1].style.fillColor, "none", "KML Feature has none fill");        
     } 
+    function test_Format_KML_extractStyleOutline(t) {
+        t.plan(2);
+        var f = new OpenLayers.Format.KML({extractStyles: true});
+        var features = f.read(test_style);
+        t.eq(features[0].style.strokeWidth, "10", "default stroke is set");
+        var features = f.read(test_style_outline);
+        t.eq(features[0].style.strokeWidth, "0", "KML Feature has no outline");
+    } 
+    function test_Format_KML_extractStyleFont(t) {
+        t.plan(2);
+        var f = new OpenLayers.Format.KML({extractStyles: true});
+        var features = f.read(test_style_font);
+        t.eq(features[0].style.fontColor, "#ff0000", "font color is set");
+        t.eq(features[0].style.fontOpacity, parseInt('87', 16) / 255, "font opacity is set");
+    } 
     function test_Format_KML_getStyle(t) {
         t.plan(1);
         var style = {t: true};
@@ -160,6 +192,72 @@
         t.eq(features[0].attributes.all_bridges.displayName, "all bridges", "read displayName from extendeddata correctly.");
     }
 
+    function test_Format_KML_extendedData_SchemaData(t) {
+        t.plan(4);
+        var f = new OpenLayers.Format.KML();
+        var features = f.read(OpenLayers.Util.getElement("kml_extendeddata2").value);
+        t.eq(features[0].attributes.TrailHeadName.value, "Pi in the sky", "read value from extendeddata (schema data) correctly.");
+        t.eq(features[0].attributes.TrailHeadName.displayName, "TrailHeadName", "read displayName from extendeddata correctly");
+        t.eq(features[0].attributes.ElevationGain.value, "10", "read value from extendeddata (schema data) correctly.");
+        t.eq(features[0].attributes.ElevationGain.displayName, "ElevationGain", "read displayName from extendeddata correctly");
+    }
+
+    function test_Format_KML_placemarkName(t) {
+        t.plan(3);
+        
+        var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0));
+        var f = new OpenLayers.Format.KML();
+
+        t.eq(f.read(f.write(feature))[0].attributes.name, feature.id, "placemark name from feature.id");
+
+        feature.attributes.name = "placemark name from attributes.name";
+        t.eq(f.read(f.write(feature))[0].attributes.name, feature.attributes.name, "placemark name from attributes.name");
+        feature.style = {
+            label: "placemark name from style.label"
+        };
+        t.eq(f.read(f.write(feature))[0].attributes.name, feature.style.label, "placemark name from style.label");
+    }
+    
+    function test_extractTracks(t) {
+        
+        t.plan(12);
+        
+        var xml = new OpenLayers.Format.XML(); 
+        var doc = xml.read(document.getElementById("macnoise.kml").firstChild.nodeValue);
+        
+        var format = new OpenLayers.Format.KML({
+            extractTracks: true,
+            trackAttributes: ["speed"] // additional custom attributes
+        });
+        
+        var features = format.read(doc.documentElement);
+        t.eq(features.length, 170, "got 170 features");
+        
+        var attr = features[4].attributes;
+        
+        // standard track point attributes
+        t.ok(attr.when instanceof Date, "features have when attribute");
+        t.eq(attr.when.getTime(), 1272736815000, "correct time for fifth feature");
+        t.eq(attr.altitude, 1006, "altitude parsed");
+        t.eq(attr.heading, 230, "heading parsed");
+        t.eq(attr.tilt, 0, "tilt parsed");
+        t.eq(attr.roll, 0, "roll parsed");
+        
+        // custom track attributes (all features acquire from the placemark)
+        t.eq(attr.name, "B752", "correct name");
+        t.eq(attr.adflag, "A", "correct adflag");
+        t.eq(attr.flightid, "DAL2973", "correct flightid");
+        
+        // additional per point attributes (determined by trackAttributes property)
+        t.eq(attr.speed, "166", "correct speed");
+        
+        var exp = new OpenLayers.Geometry.Point(-93.0753620391713, 44.9879724110872);
+        exp.z = 1006;
+        t.geom_eq(features[4].geometry, exp, "correct geometry");
+        
+    }
+    
+
     </script> 
 </head> 
 <body> 
@@ -209,5 +307,909 @@
 </Document>
 </kml>
 </textarea>
+    <textarea id="kml_extendeddata2" style="display:none">
+<kml xmlns="http://earth.google.com/kml/2.2">
+<Document>
+<Placemark>
+  <name>Easy trail</name>
+  <ExtendedData>
+    <SchemaData schemaUrl="#TrailHeadTypeId">
+      <SimpleData name="TrailHeadName">Pi in the sky</SimpleData>
+      <SimpleData name="TrailLength">3.14159</SimpleData>
+      <SimpleData name="ElevationGain">10</SimpleData>
+    </SchemaData>
+    </ExtendedData>
+    <Point>
+      <coordinates>-122.000,37.002</coordinates>
+    </Point>
+</Placemark>
+<Placemark>
+  <name>Difficult trail</name>
+  <ExtendedData>
+    <SchemaData schemaUrl="#TrailHeadTypeId">
+      <SimpleData name="TrailHeadName">Mount Everest</SimpleData>
+      <SimpleData name="TrailLength">347.45</SimpleData>
+      <SimpleData name="ElevationGain">10000</SimpleData>
+    </SchemaData>
+  </ExtendedData>
+  <Point>
+    <coordinates>-122.000,37.002</coordinates>
+  </Point>
+</Placemark>
+</Document>
+</kml>
+</textarea>
+
+<div id="macnoise.kml"><!--
+<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
+<Document>
+<Camera>
+  <gx:TimeStamp>
+    <when>2010-05-01T13:00:00-05:00</when>
+  </gx:TimeStamp>
+  <longitude>-93.2207</longitude>
+  <latitude>44.882</latitude>
+  <altitude>50000</altitude>
+  <heading>0</heading>
+  <tilt>0</tilt>
+</Camera>
+<Style id="arrival">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff0000ff</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id="departure">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff00ff00</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id="overflight">
+  <IconStyle>
+    <Icon>
+      <href>http://maps.macnoise.com/scripts/plane.png</href>
+    </Icon>
+  </IconStyle>
+  <LineStyle>
+    <color>ff222222</color>
+    <width>3</width>
+  </LineStyle>
+  <PolyStyle>
+    <color>7fffffff</color>
+  </PolyStyle>
+</Style>
+<Style id='rmt'>
+  <LabelStyle>
+    <color>ff0000cc</color>
+    <colorMode>normal</colorMode>
+    <scale>1</scale>
+  </LabelStyle>
+</Style>
+
+<name>Flight Tracks</name>
+<Folder>
+  <name>Arrivals</name>
+<Placemark>
+  <name>B752</name>
+  <adflag>A</adflag>
+  <flightid>DAL2973</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:33-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.0658625188843 44.9949645987875 1036</gx:coord>
+    <gx:coord>-93.0664690096445 44.9945424635331 1036</gx:coord>
+    <gx:coord>-93.0694347065378 44.9923936108644 1036</gx:coord>
+    <gx:coord>-93.0722946883822 44.9901649091109 1006</gx:coord>
+    <gx:coord>-93.0753620391713 44.9879724110872 1006</gx:coord>
+    <gx:coord>-93.078638650624 44.985904678007 975</gx:coord>
+    <gx:coord>-93.0817463907976 44.9836868456013 975</gx:coord>
+    <gx:coord>-93.0847749343212 44.9813998515538 945</gx:coord>
+    <gx:coord>-93.0879207383429 44.9791066547511 914</gx:coord>
+    <gx:coord>-93.091282218058 44.976822731273 914</gx:coord>
+    <gx:coord>-93.0945882606646 44.9745372955479 884</gx:coord>
+    <gx:coord>-93.0979053364864 44.9722421846492 884</gx:coord>
+    <gx:coord>-93.1012678619471 44.9698451058525 853</gx:coord>
+    <gx:coord>-93.1044570741037 44.967424293466 853</gx:coord>
+    <gx:coord>-93.1068079756418 44.9657037851018 853</gx:coord>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <speed>162</speed>
+    <speed>160</speed>
+    <speed>159</speed>
+    <speed>165</speed>
+    <speed>166</speed>
+    <speed>174</speed>
+    <speed>170</speed>
+    <speed>172</speed>
+    <speed>180</speed>
+    <speed>176</speed>
+    <speed>177</speed>
+    <speed>177</speed>
+    <speed>180</speed>
+    <speed>184</speed>
+    <speed>177</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>TCF7521</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:04-05</when>
+    <when>2010-05-01T13:00:09-05</when>
+    <when>2010-05-01T13:00:13-05</when>
+    <when>2010-05-01T13:00:18-05</when>
+    <when>2010-05-01T13:00:23-05</when>
+    <when>2010-05-01T13:00:27-05</when>
+    <when>2010-05-01T13:00:32-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:41-05</when>
+    <when>2010-05-01T13:00:46-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:55-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.3806146339391 44.8823651507134 2743</gx:coord>
+    <gx:coord>-93.3773041814209 44.887531728655 2743</gx:coord>
+    <gx:coord>-93.3742856469083 44.8942041806778 2743</gx:coord>
+    <gx:coord>-93.3722375106026 44.9009231720158 2743</gx:coord>
+    <gx:coord>-93.3711934089417 44.9077495987718 2712</gx:coord>
+    <gx:coord>-93.3707288919852 44.9145219645156 2712</gx:coord>
+    <gx:coord>-93.3703882714439 44.921240089024 2682</gx:coord>
+    <gx:coord>-93.3700882719793 44.9278850664392 2682</gx:coord>
+    <gx:coord>-93.369810041597 44.934389356737 2651</gx:coord>
+    <gx:coord>-93.3696836566166 44.9408553642446 2651</gx:coord>
+    <gx:coord>-93.3695425129226 44.9473561165969 2621</gx:coord>
+    <gx:coord>-93.3693185423471 44.9537360442564 2621</gx:coord>
+    <gx:coord>-93.3693194298816 44.9599975904123 2590</gx:coord>
+    <gx:coord>-93.3694031671108 44.9661411653607 2590</gx:coord>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>20 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>360 0 0</gx:angles>
+    <speed>376</speed>
+    <speed>367</speed>
+    <speed>361</speed>
+    <speed>371</speed>
+    <speed>367</speed>
+    <speed>363</speed>
+    <speed>359</speed>
+    <speed>356</speed>
+    <speed>352</speed>
+    <speed>347</speed>
+    <speed>343</speed>
+    <speed>347</speed>
+    <speed>334</speed>
+    <speed>337</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>BE33</name>
+  <adflag>A</adflag>
+  <flightid>N38175</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:02-05</when>
+    <when>2010-05-01T13:00:07-05</when>
+    <when>2010-05-01T13:00:12-05</when>
+    <when>2010-05-01T13:00:16-05</when>
+    <when>2010-05-01T13:00:21-05</when>
+    <when>2010-05-01T13:00:25-05</when>
+    <when>2010-05-01T13:00:30-05</when>
+    <when>2010-05-01T13:00:35-05</when>
+    <when>2010-05-01T13:00:39-05</when>
+    <when>2010-05-01T13:00:44-05</when>
+    <when>2010-05-01T13:00:49-05</when>
+    <when>2010-05-01T13:00:53-05</when>
+    <when>2010-05-01T13:00:58-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.0144637208028 44.6541474764804 1006</gx:coord>
+    <gx:coord>-93.0162681345228 44.6547274296664 1006</gx:coord>
+    <gx:coord>-93.0196734868835 44.6559915702004 975</gx:coord>
+    <gx:coord>-93.0231899415297 44.657188463998 945</gx:coord>
+    <gx:coord>-93.0267619421777 44.6582849847887 945</gx:coord>
+    <gx:coord>-93.0302021384369 44.6594728216183 914</gx:coord>
+    <gx:coord>-93.0338776768471 44.6606515995762 914</gx:coord>
+    <gx:coord>-93.0375866343814 44.6618806707998 884</gx:coord>
+    <gx:coord>-93.0411146687035 44.6632657982455 884</gx:coord>
+    <gx:coord>-93.0447829038862 44.6646495821585 884</gx:coord>
+    <gx:coord>-93.0486933143218 44.6659856209571 914</gx:coord>
+    <gx:coord>-93.0525604964428 44.6672664774449 884</gx:coord>
+    <gx:coord>-93.0559892061682 44.6686325276705 884</gx:coord>
+    <gx:coord>-93.0595122787868 44.6700360197293 884</gx:coord>
+    <gx:coord>-93.0610274392619 44.6706087373734 884</gx:coord>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>290 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <gx:angles>300 0 0</gx:angles>
+    <speed>150</speed>
+    <speed>156</speed>
+    <speed>152</speed>
+    <speed>156</speed>
+    <speed>151</speed>
+    <speed>152</speed>
+    <speed>160</speed>
+    <speed>157</speed>
+    <speed>159</speed>
+    <speed>158</speed>
+    <speed>158</speed>
+    <speed>160</speed>
+    <speed>155</speed>
+    <speed>155</speed>
+    <speed>156</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>A319</name>
+  <adflag>A</adflag>
+  <flightid>DAL1588</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:04-05</when>
+    <when>2010-05-01T13:00:08-05</when>
+    <when>2010-05-01T13:00:13-05</when>
+    <when>2010-05-01T13:00:18-05</when>
+    <when>2010-05-01T13:00:22-05</when>
+    <when>2010-05-01T13:00:27-05</when>
+    <when>2010-05-01T13:00:31-05</when>
+    <when>2010-05-01T13:00:36-05</when>
+    <when>2010-05-01T13:00:41-05</when>
+    <when>2010-05-01T13:00:45-05</when>
+    <when>2010-05-01T13:00:50-05</when>
+    <when>2010-05-01T13:00:55-05</when>
+    <when>2010-05-01T13:00:59-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.6927825194056 44.7952011849485 3011</gx:coord>
+    <gx:coord>-93.6850156681578 44.7968042586582 2987</gx:coord>
+    <gx:coord>-93.6752785488692 44.7990458605003 2956</gx:coord>
+    <gx:coord>-93.6657083011645 44.8014897663497 2926</gx:coord>
+    <gx:coord>-93.6560029615388 44.803768841381 2865</gx:coord>
+    <gx:coord>-93.6462045264035 44.8058749817725 2834</gx:coord>
+    <gx:coord>-93.6365671200126 44.8080848199989 2804</gx:coord>
+    <gx:coord>-93.6269933807039 44.8102767000109 2773</gx:coord>
+    <gx:coord>-93.6175405757462 44.8123960709083 2743</gx:coord>
+    <gx:coord>-93.6082528975965 44.8146455509748 2743</gx:coord>
+    <gx:coord>-93.599077315807 44.816765612372 2743</gx:coord>
+    <gx:coord>-93.5899428762254 44.8186933623744 2743</gx:coord>
+    <gx:coord>-93.5809104439923 44.8205403457841 2743</gx:coord>
+    <gx:coord>-93.5720785209701 44.8224608846058 2743</gx:coord>
+    <gx:coord>-93.5703603013364 44.8228739543212 2743</gx:coord>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <gx:angles>70 0 0</gx:angles>
+    <speed>390</speed>
+    <speed>383</speed>
+    <speed>397</speed>
+    <speed>390</speed>
+    <speed>405</speed>
+    <speed>388</speed>
+    <speed>386</speed>
+    <speed>397</speed>
+    <speed>377</speed>
+    <speed>373</speed>
+    <speed>367</speed>
+    <speed>362</speed>
+    <speed>365</speed>
+    <speed>350</speed>
+    <speed>354</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E145</name>
+  <adflag>A</adflag>
+  <flightid>CHQ1453</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-92.5727580977974 45.0236058844647 2530</gx:coord>
+    <gx:coord>-92.5742776202954 45.0237913896498 2530</gx:coord>
+    <gx:coord>-92.5803397933112 45.0241784662561 2499</gx:coord>
+    <gx:coord>-92.5865075192046 45.0247891381303 2469</gx:coord>
+    <gx:coord>-92.5926877928765 45.0257073410966 2469</gx:coord>
+    <gx:coord>-92.5986546763805 45.0261844476041 2438</gx:coord>
+    <gx:coord>-92.6046737535477 45.0267206733977 2438</gx:coord>
+    <gx:coord>-92.6106885874739 45.0275061986719 2438</gx:coord>
+    <gx:coord>-92.616359210337 45.027935793162 2438</gx:coord>
+    <gx:coord>-92.6220735719954 45.028379077688 2438</gx:coord>
+    <gx:coord>-92.6280403097635 45.0290552550566 2438</gx:coord>
+    <gx:coord>-92.6341725652711 45.029824064212 2438</gx:coord>
+    <gx:coord>-92.640279209769 45.0304963952702 2438</gx:coord>
+    <gx:coord>-92.6463747377703 45.0311129317319 2438</gx:coord>
+    <gx:coord>-92.650043383232 45.0314890298388 2438</gx:coord>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <speed>235</speed>
+    <speed>246</speed>
+    <speed>239</speed>
+    <speed>244</speed>
+    <speed>234</speed>
+    <speed>232</speed>
+    <speed>238</speed>
+    <speed>227</speed>
+    <speed>228</speed>
+    <speed>229</speed>
+    <speed>229</speed>
+    <speed>232</speed>
+    <speed>228</speed>
+    <speed>232</speed>
+    <speed>236</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>CPZ5695</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:25-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-92.3689380245182 45.0389467469425 2804</gx:coord>
+    <gx:coord>-92.3759530819834 45.0380951007958 2773</gx:coord>
+    <gx:coord>-92.3831159633175 45.0369957486846 2712</gx:coord>
+    <gx:coord>-92.3901362714549 45.0355238496347 2651</gx:coord>
+    <gx:coord>-92.3970814910858 45.0339385808083 2621</gx:coord>
+    <gx:coord>-92.4043121546626 45.032585906621 2560</gx:coord>
+    <gx:coord>-92.4118367565321 45.0319048652958 2499</gx:coord>
+    <gx:coord>-92.419078934653 45.030875157485 2469</gx:coord>
+    <gx:coord>-92.4262095560369 45.0291153314744 2438</gx:coord>
+    <gx:coord>-92.4335237384463 45.0273941113051 2438</gx:coord>
+    <gx:coord>-92.4408178608932 45.0260076351757 2438</gx:coord>
+    <gx:coord>-92.4451575746228 45.0254275529773 2438</gx:coord>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>250 0 0</gx:angles>
+    <gx:angles>260 0 0</gx:angles>
+    <speed>277</speed>
+    <speed>288</speed>
+    <speed>283</speed>
+    <speed>291</speed>
+    <speed>283</speed>
+    <speed>284</speed>
+    <speed>298</speed>
+    <speed>288</speed>
+    <speed>288</speed>
+    <speed>278</speed>
+    <speed>283</speed>
+    <speed>288</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>DC95</name>
+  <adflag>A</adflag>
+  <flightid>DAL2858</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:03-05</when>
+    <when>2010-05-01T13:00:07-05</when>
+    <when>2010-05-01T13:00:12-05</when>
+    <when>2010-05-01T13:00:17-05</when>
+    <when>2010-05-01T13:00:21-05</when>
+    <when>2010-05-01T13:00:26-05</when>
+    <when>2010-05-01T13:00:30-05</when>
+    <when>2010-05-01T13:00:35-05</when>
+    <when>2010-05-01T13:00:40-05</when>
+    <when>2010-05-01T13:00:44-05</when>
+    <when>2010-05-01T13:00:49-05</when>
+    <when>2010-05-01T13:00:54-05</when>
+    <when>2010-05-01T13:00:58-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.1962465696187 44.4584257162471 3078</gx:coord>
+    <gx:coord>-93.1954858158128 44.462643897726 3078</gx:coord>
+    <gx:coord>-93.1945524569257 44.4696206853623 3048</gx:coord>
+    <gx:coord>-93.1935347734104 44.4765680167011 3048</gx:coord>
+    <gx:coord>-93.1921548885013 44.4834366892852 3048</gx:coord>
+    <gx:coord>-93.1912787899895 44.4902740201102 3048</gx:coord>
+    <gx:coord>-93.190869393024 44.496999598511 3048</gx:coord>
+    <gx:coord>-93.190355669541 44.503701889363 3048</gx:coord>
+    <gx:coord>-93.1899042890233 44.510392533924 3048</gx:coord>
+    <gx:coord>-93.1894352972433 44.5171043633827 3048</gx:coord>
+    <gx:coord>-93.1887272976791 44.523838031578 3017</gx:coord>
+    <gx:coord>-93.1882343860587 44.5305421014878 2987</gx:coord>
+    <gx:coord>-93.1878483537445 44.5373007218153 2987</gx:coord>
+    <gx:coord>-93.187206305476 44.5440099500882 2956</gx:coord>
+    <gx:coord>-93.1870547021374 44.5466877366242 2956</gx:coord>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>10 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <gx:angles>0 0 0</gx:angles>
+    <speed>378</speed>
+    <speed>370</speed>
+    <speed>381</speed>
+    <speed>373</speed>
+    <speed>384</speed>
+    <speed>367</speed>
+    <speed>365</speed>
+    <speed>377</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>362</speed>
+    <speed>368</speed>
+    <speed>355</speed>
+    <speed>362</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>B737</name>
+  <adflag>A</adflag>
+  <flightid>SWA1488</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:11-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:48-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-92.7436038977339 45.0176449723009 2438</gx:coord>
+    <gx:coord>-92.745419752639 45.0178405701636 2438</gx:coord>
+    <gx:coord>-92.7525586927583 45.0181852080204 2438</gx:coord>
+    <gx:coord>-92.7599978682742 45.0189437491361 2438</gx:coord>
+    <gx:coord>-92.7673964649616 45.0200176804669 2438</gx:coord>
+    <gx:coord>-92.7743047878147 45.0206512321095 2438</gx:coord>
+    <gx:coord>-92.7812211106102 45.0212438545962 2438</gx:coord>
+    <gx:coord>-92.7880905786106 45.0219352711124 2438</gx:coord>
+    <gx:coord>-92.7948110303679 45.0225135550872 2438</gx:coord>
+    <gx:coord>-92.8016256231407 45.0231539091809 2377</gx:coord>
+    <gx:coord>-92.808436321378 45.0237782407713 2316</gx:coord>
+    <gx:coord>-92.8153060032773 45.0245123996427 2255</gx:coord>
+    <gx:coord>-92.8220950756464 45.0250388052127 2194</gx:coord>
+    <gx:coord>-92.8289929014999 45.0256725515916 2164</gx:coord>
+    <gx:coord>-92.8342709686589 45.0263726025032 2118.25</gx:coord>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <gx:angles>280 0 0</gx:angles>
+    <speed>280</speed>
+    <speed>293</speed>
+    <speed>284</speed>
+    <speed>288</speed>
+    <speed>274</speed>
+    <speed>272</speed>
+    <speed>279</speed>
+    <speed>263</speed>
+    <speed>263</speed>
+    <speed>262</speed>
+    <speed>262</speed>
+    <speed>275</speed>
+    <speed>270</speed>
+    <speed>277</speed>
+    <speed>287</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>A318</name>
+  <adflag>A</adflag>
+  <flightid>FFT106</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:05-05</when>
+    <when>2010-05-01T13:00:09-05</when>
+    <when>2010-05-01T13:00:14-05</when>
+    <when>2010-05-01T13:00:19-05</when>
+    <when>2010-05-01T13:00:23-05</when>
+    <when>2010-05-01T13:00:28-05</when>
+    <when>2010-05-01T13:00:33-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:42-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:56-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.2974568508014 45.0687622602847 1432</gx:coord>
+    <gx:coord>-93.2934457905393 45.0660257042941 1371</gx:coord>
+    <gx:coord>-93.2902010482642 45.0627382200457 1341</gx:coord>
+    <gx:coord>-93.2880735868205 45.0592062737728 1280</gx:coord>
+    <gx:coord>-93.2866251180089 45.0556538417996 1280</gx:coord>
+    <gx:coord>-93.2855706436895 45.0521555770546 1249</gx:coord>
+    <gx:coord>-93.2848929213344 45.0486326683558 1249</gx:coord>
+    <gx:coord>-93.284149302237 45.0450445279501 1219</gx:coord>
+    <gx:coord>-93.2832681542582 45.0414770478452 1219</gx:coord>
+    <gx:coord>-93.2822163760078 45.0378266141909 1219</gx:coord>
+    <gx:coord>-93.2810695206555 45.0339762188888 1249</gx:coord>
+    <gx:coord>-93.2800852709943 45.0300242656845 1249</gx:coord>
+    <gx:coord>-93.2789451826991 45.026165428423 1249</gx:coord>
+    <gx:coord>-93.2776553627852 45.0222881273358 1219</gx:coord>
+    <gx:angles>140 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>150 0 0</gx:angles>
+    <gx:angles>160 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <gx:angles>170 0 0</gx:angles>
+    <speed>212</speed>
+    <speed>205</speed>
+    <speed>208</speed>
+    <speed>203</speed>
+    <speed>201</speed>
+    <speed>196</speed>
+    <speed>196</speed>
+    <speed>197</speed>
+    <speed>202</speed>
+    <speed>205</speed>
+    <speed>216</speed>
+    <speed>215</speed>
+    <speed>222</speed>
+    <speed>231</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name></name>
+  <adflag>A</adflag>
+  <flightid></flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:05-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:14-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:33-05</when>
+    <when>2010-05-01T13:00:37-05</when>
+    <when>2010-05-01T13:00:42-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:51-05</when>
+    <when>2010-05-01T13:00:56-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-93.5287325331323 45.3502794027397 731</gx:coord>
+    <gx:coord>-93.5305174337715 45.3463816209029 731</gx:coord>
+    <gx:coord>-93.532323089283 45.3433065196778 731</gx:coord>
+    <gx:coord>-93.5344374505075 45.3397938806867 731</gx:coord>
+    <gx:coord>-93.5365879669744 45.3355152994798 731</gx:coord>
+    <gx:coord>-93.538455345577 45.3317693717468 731</gx:coord>
+    <gx:coord>-93.5402440337749 45.3288175816964 731</gx:coord>
+    <gx:coord>-93.5420054353005 45.3261482119682 701</gx:coord>
+    <gx:coord>-93.5437972875724 45.3236486426325 701</gx:coord>
+    <gx:coord>-93.5449025453586 45.3213557809437 670</gx:coord>
+    <gx:coord>-93.5460939368394 45.3190373998605 670</gx:coord>
+    <gx:coord>-93.5479457332637 45.3165177805485 670</gx:coord>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <gx:angles>200 0 0</gx:angles>
+    <speed>202</speed>
+    <speed>180</speed>
+    <speed>166</speed>
+    <speed>171</speed>
+    <speed>162</speed>
+    <speed>157</speed>
+    <speed>143</speed>
+    <speed>145</speed>
+    <speed>156</speed>
+    <speed>147</speed>
+    <speed>147</speed>
+    <speed>150</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>CRJ2</name>
+  <adflag>A</adflag>
+  <flightid>SKW4805</flightid>
+  <styleUrl>#arrival</styleUrl>
+</Placemark>
+<Placemark>
+  <name>CRJ2</name>
+  <adflag>A</adflag>
+  <flightid>FLG4092</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:44-05</when>
+    <when>2010-05-01T13:00:49-05</when>
+    <when>2010-05-01T13:00:54-05</when>
+    <gx:coord>-93.1836067392297 44.9110362339843 432.2</gx:coord>
+    <gx:coord>-93.1841170614853 44.910663862492 426</gx:coord>
+    <gx:coord>-93.1867007876887 44.908842129317 426</gx:coord>
+    <gx:coord>-93.1893728799637 44.9069842219291 396</gx:coord>
+    <gx:coord>-93.1919479660705 44.9051548529609 365</gx:coord>
+    <gx:coord>-93.1944798212107 44.9032897679148 365</gx:coord>
+    <gx:coord>-93.197164452306 44.9014210542153 335</gx:coord>
+    <gx:coord>-93.1996234874761 44.8995719817206 335</gx:coord>
+    <gx:coord>-93.2021701211426 44.8975674983317 304</gx:coord>
+    <gx:coord>-93.2050345971567 44.8955942303701 304</gx:coord>
+    <gx:coord>-93.2075455037487 44.8938556558558 304</gx:coord>
+    <gx:coord>-93.2100820128846 44.8918590963212 304</gx:coord>
+    <gx:coord>-93.2127524858241 44.89000250047 256</gx:coord>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>230 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <gx:angles>220 0 0</gx:angles>
+    <speed>141</speed>
+    <speed>138</speed>
+    <speed>136</speed>
+    <speed>141</speed>
+    <speed>141</speed>
+    <speed>142</speed>
+    <speed>143</speed>
+    <speed>139</speed>
+    <speed>140</speed>
+    <speed>134</speed>
+    <speed>136</speed>
+    <speed>136</speed>
+    <speed>123</speed>
+</gx:Track></Placemark>
+<Placemark>
+  <name>E170</name>
+  <adflag>A</adflag>
+  <flightid>CPZ5667</flightid>
+  <styleUrl>#arrival</styleUrl>
+<gx:Track>
+    <altitudeMode>absolute</altitudeMode>
+    <extrude>1</extrude>
+    <when>2010-05-01T13:00:00-05</when>
+    <when>2010-05-01T13:00:01-05</when>
+    <when>2010-05-01T13:00:06-05</when>
+    <when>2010-05-01T13:00:10-05</when>
+    <when>2010-05-01T13:00:15-05</when>
+    <when>2010-05-01T13:00:20-05</when>
+    <when>2010-05-01T13:00:24-05</when>
+    <when>2010-05-01T13:00:29-05</when>
+    <when>2010-05-01T13:00:34-05</when>
+    <when>2010-05-01T13:00:38-05</when>
+    <when>2010-05-01T13:00:43-05</when>
+    <when>2010-05-01T13:00:47-05</when>
+    <when>2010-05-01T13:00:52-05</when>
+    <when>2010-05-01T13:00:57-05</when>
+    <when>2010-05-01T13:01:00-05</when>
+    <gx:coord>-92.9496238812799 45.0117549407746 1438.2</gx:coord>
+    <gx:coord>-92.9507065768732 45.0116702587604 1432</gx:coord>
+    <gx:coord>-92.9563739191926 45.0116271226204 1432</gx:coord>
+    <gx:coord>-92.9620225732021 45.0115639668496 1432</gx:coord>
+    <gx:coord>-92.9673675587699 45.0113432900049 1402</gx:coord>
+    <gx:coord>-92.9725115032188 45.0111442254373 1402</gx:coord>
+    <gx:coord>-92.9778810091229 45.0112050922639 1371</gx:coord>
+    <gx:coord>-92.9832227114571 45.0112143826731 1371</gx:coord>
+    <gx:coord>-92.9884546803523 45.0110418166788 1341</gx:coord>
+    <gx:coord>-92.9938268606229 45.0109652220709 1341</gx:coord>
+    <gx:coord>-92.9991151069756 45.010802144845 1310</gx:coord>
+    <gx:coord>-93.0041467584036 45.0105516668541 1310</gx:coord>
+    <gx:coord>-93.0090742909164 45.0105233046799 1280</gx:coord>
+    <gx:coord>-93.0139435770527 45.0106265340001 1280</gx:coord>
+    <gx:coord>-93.0174882575928 45.0106328449121 1256.75</gx:coord>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <gx:angles>270 0 0</gx:angles>
+    <speed>214</speed>
+    <speed>207</speed>
+    <speed>202</speed>
+    <speed>208</speed>
+    <speed>207</speed>
+    <speed>205</speed>
+    <speed>203</speed>
+    <speed>202</speed>
+    <speed>209</speed>
+    <speed>199</speed>
+    <speed>196</speed>
+    <speed>200</speed>
+    <speed>193</speed>
+    <speed>194</speed>
+    <speed>185</speed>
+</gx:Track></Placemark>
+</Folder>
+<Folder>
+  <name>Departures</name>
+</Folder>
+<Folder>
+  <name>Overflights</name>
+</Folder>
+</Document>
+</kml>
+--></div>
+
 </body> 
 </html> 

Modified: sandbox/ahocevar/playground/tests/Format/OSM.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/OSM.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/OSM.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -5,7 +5,7 @@
     <script type="text/javascript">
     
     function test_Format_OSM_constructor(t) { 
-        t.plan(4); 
+        t.plan(5); 
          
         var options = {'foo': 'bar'}; 
         var format = new OpenLayers.Format.OSM(options); 
@@ -14,6 +14,8 @@
         t.eq(format.foo, "bar", "constructor sets options correctly"); 
         t.eq(typeof format.read, "function", "format has a read function"); 
         t.eq(typeof format.write, "function", "format has a write function"); 
+        t.eq(format.externalProjection.getCode(), "EPSG:4326", 
+             "default external projection is EPSG:4326"); 
     } 
     function test_Format_OSM_node(t) {
         t.plan(4);

Deleted: sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html
===================================================================
--- trunk/openlayers/tests/Format/OWSContext/v0_3_1.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,240 +0,0 @@
-<html> 
-<head> 
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-
-    function test_read_wmswfs(t) {
-        t.plan(16);
-        // taken from http://www.ogcnetwork.net/schemas/owc/0.3.1/context_nested.xml
-        // adapted: add an extra slash (roads/railways) in the Title of the WMS layer to test nesting
-        var text = '<?xml version="1.0" encoding="UTF-8"?>' +
-            '<OWSContext version="0.3.1" id="ows-context-ex-1-v3" xmlns="http://www.opengis.net/ows-context"' +
-            '	xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2"' +
-            '	xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows"' +
-            '	xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink"' +
-            '	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
-            '	xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd">' +
-            '	<General>' +
-            '		<ows:BoundingBox crs="EPSG:4326">' +
-            '			<ows:LowerCorner>-117 32</ows:LowerCorner>' +
-            '			<ows:UpperCorner>-116 33</ows:UpperCorner>' +
-            '		</ows:BoundingBox>' +
-            '		<ows:Title>OWS Context version 0.3.1 showing nested layers</ows:Title>' +
-            '	</General>' +
-            '	<ResourceList>' +
-            '		<!-- WMS Example -->' +
-            '		<Layer name="topp:major_roads" queryable="1" hidden="1">' +
-            '			<ows:Title>Tiger 2005fe major roads/railways</ows:Title>' +
-            '			<ows:OutputFormat>image/png</ows:OutputFormat>' +
-            '			<Server service="urn:ogc:serviceType:WMS" version="1.1.1">' +
-            '				<OnlineResource' +
-            '					xlink:href="http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS"/>' +
-            '			</Server>' +
-            '			<!-- WFS Example -->' +
-            '			<Layer name="topp:gnis_pop" hidden="0">' +
-            '				<ows:Title>GNIS Population</ows:Title>' +
-            '				<Server service="urn:ogc:serviceType:WFS" version="1.0.0">' +
-            '					<OnlineResource xlink:href="http://sigma.openplans.org:8080/geoserver/wfs?"/>' +
-            '				</Server>' +
-            '			</Layer>' +
-            '		</Layer>' +
-            '	</ResourceList>' +
-            '</OWSContext>';
-        var parser = new OpenLayers.Format.OWSContext();
-        var map = new OpenLayers.Map('map', {allOverlays: true, fractionalZoom: true});
-        var context = parser.read(text, {map: map});
-        t.eq(context.layers.length, 2, "2 layers parsed from OWSContext document");
-        t.eq(context.layers[1].metadata.nestingPath[0], "Tiger 2005fe major roads/railways", "Nesting path correctly set");
-        t.ok(context.layers[0] instanceof OpenLayers.Layer.WMS, "First layer is a WMS layer"); 
-        t.ok(context.layers[1] instanceof OpenLayers.Layer.Vector, "Second layer is a vector layer");
-        t.eq(context.layers[0].params.LAYERS, "topp:major_roads", "WMS layer name correctly read");
-        t.eq(context.layers[0].params.FORMAT, "image/png", "WMS format correctly read");
-        t.eq(context.layers[0].url, "http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS", "Layer url correctly read");
-        t.eq(context.layers[0].getVisibility(), false, "WMS Layer is hidden");
-        t.ok(context.layers[0].queryable, "WMS layer is queryable");
-        t.eq(context.layers[0].name, "Tiger 2005fe major roads/railways", "Title correctly set");
-        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.WFS.v1_0_0, "Vector layer configured with a WFS Protocol");
-        t.eq(context.layers[1].protocol.url, "http://sigma.openplans.org:8080/geoserver/wfs?", "WFS url set correctly");
-        t.ok(context.layers[1].strategies[0] instanceof OpenLayers.Strategy.BBOX, "BBOX strategy configured correctly");
-        t.eq(context.layers[1].name, "GNIS Population", "Title of second layer correctly set");
-        t.eq(context.layers[1].getVisibility(), true, "Second layer is visible");
-        map.zoomToExtent(new OpenLayers.Bounds(-117, 32, -116, 33));
-        var owc = parser.write(map, {id: 'ows-context-ex-1-v3', title: 'OWS Context version 0.3.1 showing nested layers'});
-        t.xml_eq(text, owc, "Can we roundtrip this nested OWSContext with a WMS and WFS layer?");
-    }
-
-    function test_write_wmswfs(t) {
-        t.plan(1);
-        var lon = 5;
-        var lat = 40;
-        var zoom = 5;
-        var map = new OpenLayers.Map( 'map' );
-        var layer = new OpenLayers.Layer.WMS(
-            "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0",
-            {layers: 'basic'},
-            {singleTile: true}
-        );
-        var wfs = new OpenLayers.Layer.Vector("myroads", {
-            strategies: [new OpenLayers.Strategy.BBOX()],
-            protocol: new OpenLayers.Protocol.WFS({
-                url:  "http://foo/wfs",
-                featureType: "roads",
-                featureNS: "http://foo/myns"
-            })
-        });
-        map.addLayers([layer, wfs]);
-        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
-
-        var owc = new OpenLayers.Format.OWSContext();
-        var output = owc.write(map, {id: 'foo'});
-        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer name="feature:roads" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">myroads</ows:Title><Server version="1.0.0" service="urn:ogc:serviceType:WFS"><OnlineResource xlink:href="http://foo/wfs" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
-        t.xml_eq(output, expected, "OWSContext with a WMS and a WFS layer generated correctly");
-    }
-
-    function test_write_wmsinlinegml(t) {
-        t.plan(1);
-        var lon = 5;
-        var lat = 40;
-        var zoom = 5;
-        var map = new OpenLayers.Map( 'map' );
-        var layer = new OpenLayers.Layer.WMS(
-            "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0",
-            {layers: 'basic'},
-            {singleTile: true}
-        );
-        map.addLayer(layer);
-        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
-
-        var vector = new OpenLayers.Layer.Vector();
-        map.addLayer(vector);
-        var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,1));
-        var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,0));
-        vector.addFeatures(feature1);
-        vector.addFeatures(feature2);
-        var owc = new OpenLayers.Format.OWSContext();
-        var output = owc.write(map, {id: 'foo'});
-        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer name="vector" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows"/><InlineGeometry><gml:boundedBy xmlns:gml="http://www.opengis.net/gml"><gml:Box><gml:coordinates decimal="." cs="," ts=" ">0,0 1,1</gml:coordinates></gml:Box></gml:boundedBy><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:vector xmlns:feature="http://mapserver.gis.umn.edu/mapserver"><feature:geometry><gml:Point><gml:coordinates decimal="." cs="," ts=" ">0,1</gml:coordinates></gml:Point></feature:geometry></feature:vector></gml:featureMember><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:vector xmlns:feature="http://mapserver.gis.umn.edu/mapserver"><feature:geometry><gml:Point><gml:coordinates decimal="." cs="," ts=" ">1,0</gml:coordinates></gml:Point></feature:geometry></feature:vector></gml:featureMember></InlineGeometry></Layer></ResourceList></OWSContext>';
-        t.xml_eq(output, expected, "OWSContext with a WMS and an inline GML vector layer generated correctly");
-    }
-
-    function test_read_inline(t) {
-        t.plan(10);
-        var text = '<?xml version="1.0" encoding="UTF-8"?><OWSContext xmlns="http://www.opengis.net/ows-context" xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.3.1" id="ows-context-ex-1-v3" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.0/owsContext.xsd"><General><ows:BoundingBox crs="urn:ogc:def:crs:EPSG:6.6:4326"><ows:LowerCorner>-117.44667178362664 32.57086210449395</ows:LowerCorner><ows:UpperCorner>-116.74066794885977 32.921986352104064</ows:UpperCorner></ows:BoundingBox><ows:Title>OWS Context version 0.3.0 Inline KML and GML examples</ows:Title></General><ResourceList><!-- WMS Example --><Layer name="topp:major_roads" queryable="1" hidden="1">	<ows:Title>Tiger 2005f
 e major roads</ows:Title>	<ows:OutputFormat>image/png</ows:OutputFormat><Server service="urn:ogc:serviceType:WMS" version="1.1.1"><OnlineResource xlink:href="http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS"/></Server></Layer><!-- Inline KML Example --><Layer name="archsites"><ows:Title>Architectural Sites</ows:Title><kml:Document><kml:name>opengeo:archsites 1 to 100</kml:name><kml:Style id="archsitesStyle"><kml:IconStyle><kml:color>ffffffff</kml:color><kml:colorMode>normal</kml:colorMode><kml:Icon><kml:href>http://maps.google.com/mapfiles/kml/pal4/icon25.png</kml:href></kml:Icon></kml:IconStyle></kml:Style><kml:Placemark id="archsites.1"><kml:name>Signature Rock</kml:name><kml:description>Signature Rock Description</kml:description><kml:styleUrl>#archsitesStyle</kml:styleUrl><kml:Point><kml:coordinates>-103.82681673,44.38162255</kml:coordinates></kml:Point></kml:Placemark></kml:Document></Layer><!-- Inline GML Example --><Layer name="coastg"><ows:Title>Coastg as GM
 L Points</ows:Title><InlineGeometry><gml:boundedBy><gml:Box><gml:coord><gml:X>-43.379</gml:X><gml:Y>72.746</gml:Y></gml:coord><gml:coord><gml:X>-43.390</gml:X><gml:Y>72.755</gml:Y></gml:coord></gml:Box></gml:boundedBy><gml:featureMember><au1:coastg xmlns:au1="http://www.ionicsoft.com/wfs" fid="coastg.0"><au1:MERGE>1</au1:MERGE><au1:AREA>0.0020000000000000005</au1:AREA><au1:PERIMETER>0.167</au1:PERIMETER><au1:GEOMETRY><gml:Polygon srsName="urn:ogc:def:crs:EPSG:6.6:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>129.29167335893825,71.9583353847737 129.29167335893825,72.0000014248896 129.33332733905414,72.0000014248896 129.33332733905414,71.9583353847737 129.29167335893825,71.9583353847737</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></au1:GEOMETRY></au1:coastg></gml:featureMember><gml:featureMember><au1:coastg xmlns:au1="http://www.ionicsoft.com/wfs" fid="coastg.1"><au1:MERGE>1</au1:MERGE><au1:AREA>0.0020000000000000005</au1:AREA><au1:PERIM
 ETER>0.167</au1:PERIMETER><au1:GEOMETRY><gml:Polygon srsName="urn:ogc:def:crs:EPSG:6.6:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>135.45832829609282,35.66666796381659 135.41667179597695,35.66666796381659 135.41667179597695,35.70833202393249 135.45832829609282,35.70833202393249 135.45832829609282,35.66666796381659</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></au1:GEOMETRY></au1:coastg></gml:featureMember></InlineGeometry></Layer></ResourceList></OWSContext>';
-        var parser = new OpenLayers.Format.OWSContext();
-        var context = parser.read(text, {map: 'map'});
-        t.ok(context.layers[1] instanceof OpenLayers.Layer.Vector, "Inline KML results in a vector layer");
-        t.eq(context.layers[1].features.length, 1, "Inline KML layer has one feature");
-        t.ok(context.layers[1].features[0].geometry instanceof OpenLayers.Geometry.Point, "KML feature is a point");
-        t.eq(context.layers[1].features[0].attributes.description, "Signature Rock Description", "KML Description correctly parsed");
-        t.eq(context.layers[1].features[0].fid, "archsites.1", "KML feature id correctly parsed");
-        t.eq(context.layers[1].features[0].style.externalGraphic, "http://maps.google.com/mapfiles/kml/pal4/icon25.png", "Style url for KML feature correctly parsed");
-        t.ok(context.layers[2] instanceof OpenLayers.Layer.Vector, "Inline GML results in a vector layer");
-        t.eq(context.layers[2].features.length, 2, "Inline GML layer has two features");
-        t.ok(context.layers[2].features[0].geometry instanceof OpenLayers.Geometry.Polygon, "GML feature is a polygon");
-        t.eq(context.layers[2].features[0].attributes.MERGE, "1", "GML attribute read correctly");
-    }
-
-    function test_read_gml(t) {
-        t.plan(5);
-        var text = '<?xml version="1.0" encoding="UTF-8"?><OWSContext version="0.3.0" id="ows-context-ex-1-v3" xmlns="http://www.opengis.net/ows-context" xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.0/owsContext.xsd"><General><ows:BoundingBox crs="urn:ogc:def:crs:EPSG:6.6:4326"><ows:LowerCorner>-117.44667178362664 32.57086210449395</ows:LowerCorner><ows:UpperCorner>-116.74066794885977 32.921986352104064</ows:UpperCorner></ows:BoundingBox><ows:Title>OWS Context version 0.3.0 examples</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0" opacity="1"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers 
 WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer><!-- Referenced GML Example --><Layer name="Landuse"><ows:Title>Boston Landuse Polygons</ows:Title><Server service="urn:ogc:serviceType:GML" version="2.1.2" title="Cadcorp GeognoSIS.NET Web Feature Service"><OnlineResource xlink:href="http://www.cadcorpdev.co.uk/gml/MassGIS/LandUse.gml"/></Server><sld:MinScaleDenominator>5000</sld:MinScaleDenominator><sld:MaxScaleDenominator>50000</sld:MaxScaleDenominator><MaxFeatures>99</MaxFeatures></Layer></ResourceList></OWSContext>';
-        var parser = new OpenLayers.Format.OWSContext();
-        var context = parser.read(text, {map: 'map'});
-        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.HTTP, "serviceType GML is translated into an HTTP Protocol");
-        t.eq(context.layers[1].protocol.url, "http://www.cadcorpdev.co.uk/gml/MassGIS/LandUse.gml", "Url of GML file correctly set");
-        t.ok(context.layers[1].protocol.format instanceof OpenLayers.Format.GML, "GML Format associated with protocol");
-        t.eq(Math.round(context.layers[1].minScale), 50000, "Minscale correctly read");
-        t.eq(Math.round(context.layers[1].maxScale), 5000, "Maxscale correctly read");
-    }
-
-    function test_read_kml(t) {
-        t.plan(3);
-        var text = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 27.9150390625</ows:LowerCorner><ows:UpperCorner>15.986328125 52.0849609375</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0" opacity="1"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Serv
 er></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">KML</ows:Title><Server version="2.2" service="urn:ogc:serviceType:KML"><OnlineResource xlink:href="http://foo/sundials.kml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
-        var parser = new OpenLayers.Format.OWSContext();
-        var context = parser.read(text, {map: 'map'});
-        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.HTTP, "serviceType KML is translated into an HTTP Protocol");
-        t.eq(context.layers[1].protocol.url, "http://foo/sundials.kml", "Url of KML file correctly set");
-        t.ok(context.layers[1].protocol.format instanceof OpenLayers.Format.KML, "KML Format associated with protocol");
-    }
-
-    function test_write_gml(t) {
-        t.plan(1);
-        var lon = 5;
-        var lat = 40;
-        var zoom = 5;
-        var map = new OpenLayers.Map( 'map' );
-        var layer = new OpenLayers.Layer.WMS(
-            "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0",
-            {layers: 'basic'},
-            {singleTile: true}
-        );
-        var sundials = new OpenLayers.Layer.Vector("GML", {
-            projection: map.displayProjection,
-            strategies: [new OpenLayers.Strategy.Fixed()],
-            protocol: new OpenLayers.Protocol.HTTP({
-                url: "http://foo/sundials.gml",
-                format: new OpenLayers.Format.GML()
-            })
-        });
-        map.addLayers([layer, sundials]);
-        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
-
-        var owc = new OpenLayers.Format.OWSContext();
-        var output = owc.write(map, {id: 'foo'});
-        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">GML</ows:Title><Server version="2.1.2" service="urn:ogc:serviceType:GML"><OnlineResource xlink:href="http://foo/sundials.gml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
-        t.xml_eq(output, expected, "OWSContext with a WMS and a GML vector layer generated correctly");
-    }
-
-    function test_write_kml(t) {
-        t.plan(1);
-        var lon = 5;
-        var lat = 40;
-        var zoom = 5;
-        var map = new OpenLayers.Map( 'map' );
-        var layer = new OpenLayers.Layer.WMS(
-            "OpenLayers WMS",
-            "http://labs.metacarta.com/wms/vmap0",
-            {layers: 'basic'},
-            {singleTile: true}
-        );
-        var sundials = new OpenLayers.Layer.Vector("KML", {
-            projection: map.displayProjection,
-            strategies: [new OpenLayers.Strategy.Fixed()],
-            protocol: new OpenLayers.Protocol.HTTP({
-                url: "http://foo/sundials.kml",
-                format: new OpenLayers.Format.KML({
-                    extractStyles: true
-                })
-            })
-        });
-        map.addLayers([layer, sundials]);
-        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
-
-        var owc = new OpenLayers.Format.OWSContext();
-        var output = owc.write(map, {id: 'foo'});
-        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">KML</ows:Title><Server version="2.2" service="urn:ogc:serviceType:KML"><OnlineResource xlink:href="http://foo/sundials.kml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
-        t.xml_eq(output, expected, "OWSContext with a WMS and a KML vector layer generated correctly");
-    }
-
-    function test_nested(t) {
-        t.plan(4);
-        var text = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="machu" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-40 30</ows:LowerCorner><ows:UpperCorner>55 125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">General Bathymetric Chart</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">GEBCO</ows:Title><Layer name="GEBCO" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">GEBCO</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><Onlin
 eResource xlink:href="http://foo/bar_bathymetry?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/gebco.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Administrative boundaries</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">National boundaries</ows:Title><Layer name="GAUL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">GAUL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_topography?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource
  xlink:href="http://foo/services/geoservices/legends/machu/administrative_boundaries_land.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Maritime boundaries</ows:Title><Layer name="World_Maritime_Boundaries_v4_20090811" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">World_Maritime_Boundaries_v4_20090811</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_topography?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/administrative_boundaries_sea.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer
 ><ows:Title xmlns:ows="http://www.opengis.net/ows">Cultural Heritage Underwater</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Sites</ows:Title><Layer name="ARCH_NL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_NL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_nl?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_PL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_PL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat>
 <Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pl?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_PT" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_PT</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pt?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.o
 rg/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_BE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_BE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_be?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_SE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_SE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_se?" xml
 ns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_DE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_DE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_de?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_UK" queryable="1" hidden="0"><ows:T
 itle xmlns:ows="http://www.opengis.net/ows">ARCH_UK</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_uk?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Theme1</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">layer1</ows:Title><Layer name="TEST_AREA_BE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_BE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:s
 erviceType:WMS"><OnlineResource xlink:href="http://foo/bar_be?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer><Layer name="TEST_AREA_PT" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_PT</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pt?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Theme2</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">layer1</ows:Title><Layer name="TEST_AREA_SE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_SE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_se?" xml
 ns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></Layer></Layer></ResourceList></OWSContext>';
-        var parser = new OpenLayers.Format.OWSContext();
-        var map = new OpenLayers.Map('map', {allOverlays: true, fractionalZoom: true});
-        var context = parser.read(text, {map: map});
-        t.eq(map.layers.length, 13, "13 layers parsed from document");
-        t.eq(map.layers[0].metadata.nestingPath.join("/"), "General Bathymetric Chart/GEBCO", "Category layers read correctly");
-        t.eq(map.layers[0].metadata.styles[0].legend.url, "http://foo/services/geoservices/legends/machu/gebco.png", "Legend url correctly parsed");
-        map.zoomToExtent(new OpenLayers.Bounds(-40, 30, 55, 125));
-        var owc = parser.write(map, {id: 'machu'});
-        t.xml_eq(text, owc, "Can we roundtrip nested OWSContext successfully?");
-    }
-
-    </script> 
-</head>
-<body>
-<div id="map" style="width:500px;height:500px"></div>
-</body>
-</html>

Copied: sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html (from rev 10919, trunk/openlayers/tests/Format/OWSContext/v0_3_1.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/OWSContext/v0_3_1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,240 @@
+<html> 
+<head> 
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_read_wmswfs(t) {
+        t.plan(16);
+        // taken from http://www.ogcnetwork.net/schemas/owc/0.3.1/context_nested.xml
+        // adapted: add an extra slash (roads/railways) in the Title of the WMS layer to test nesting
+        var text = '<?xml version="1.0" encoding="UTF-8"?>' +
+            '<OWSContext version="0.3.1" id="ows-context-ex-1-v3" xmlns="http://www.opengis.net/ows-context"' +
+            '	xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2"' +
+            '	xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows"' +
+            '	xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink"' +
+            '	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
+            '	xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd">' +
+            '	<General>' +
+            '		<ows:BoundingBox crs="EPSG:4326">' +
+            '			<ows:LowerCorner>-117 32</ows:LowerCorner>' +
+            '			<ows:UpperCorner>-116 33</ows:UpperCorner>' +
+            '		</ows:BoundingBox>' +
+            '		<ows:Title>OWS Context version 0.3.1 showing nested layers</ows:Title>' +
+            '	</General>' +
+            '	<ResourceList>' +
+            '		<!-- WMS Example -->' +
+            '		<Layer name="topp:major_roads" queryable="1" hidden="1">' +
+            '			<ows:Title>Tiger 2005fe major roads/railways</ows:Title>' +
+            '			<ows:OutputFormat>image/png</ows:OutputFormat>' +
+            '			<Server service="urn:ogc:serviceType:WMS" version="1.1.1">' +
+            '				<OnlineResource' +
+            '					xlink:href="http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS"/>' +
+            '			</Server>' +
+            '			<!-- WFS Example -->' +
+            '			<Layer name="topp:gnis_pop" hidden="0">' +
+            '				<ows:Title>GNIS Population</ows:Title>' +
+            '				<Server service="urn:ogc:serviceType:WFS" version="1.0.0">' +
+            '					<OnlineResource xlink:href="http://sigma.openplans.org:8080/geoserver/wfs?"/>' +
+            '				</Server>' +
+            '			</Layer>' +
+            '		</Layer>' +
+            '	</ResourceList>' +
+            '</OWSContext>';
+        var parser = new OpenLayers.Format.OWSContext();
+        var map = new OpenLayers.Map('map', {allOverlays: true, fractionalZoom: true});
+        var context = parser.read(text, {map: map});
+        t.eq(context.layers.length, 2, "2 layers parsed from OWSContext document");
+        t.eq(context.layers[1].metadata.nestingPath[0], "Tiger 2005fe major roads/railways", "Nesting path correctly set");
+        t.ok(context.layers[0] instanceof OpenLayers.Layer.WMS, "First layer is a WMS layer"); 
+        t.ok(context.layers[1] instanceof OpenLayers.Layer.Vector, "Second layer is a vector layer");
+        t.eq(context.layers[0].params.LAYERS, "topp:major_roads", "WMS layer name correctly read");
+        t.eq(context.layers[0].params.FORMAT, "image/png", "WMS format correctly read");
+        t.eq(context.layers[0].url, "http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS", "Layer url correctly read");
+        t.eq(context.layers[0].getVisibility(), false, "WMS Layer is hidden");
+        t.ok(context.layers[0].queryable, "WMS layer is queryable");
+        t.eq(context.layers[0].name, "Tiger 2005fe major roads/railways", "Title correctly set");
+        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.WFS.v1_0_0, "Vector layer configured with a WFS Protocol");
+        t.eq(context.layers[1].protocol.url, "http://sigma.openplans.org:8080/geoserver/wfs?", "WFS url set correctly");
+        t.ok(context.layers[1].strategies[0] instanceof OpenLayers.Strategy.BBOX, "BBOX strategy configured correctly");
+        t.eq(context.layers[1].name, "GNIS Population", "Title of second layer correctly set");
+        t.eq(context.layers[1].getVisibility(), true, "Second layer is visible");
+        map.zoomToExtent(new OpenLayers.Bounds(-117, 32, -116, 33));
+        var owc = parser.write(map, {id: 'ows-context-ex-1-v3', title: 'OWS Context version 0.3.1 showing nested layers'});
+        t.xml_eq(text, owc, "Can we roundtrip this nested OWSContext with a WMS and WFS layer?");
+    }
+
+    function test_write_wmswfs(t) {
+        t.plan(1);
+        var lon = 5;
+        var lat = 40;
+        var zoom = 5;
+        var map = new OpenLayers.Map( 'map' );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://labs.metacarta.com/wms/vmap0",
+            {layers: 'basic'},
+            {singleTile: true}
+        );
+        var wfs = new OpenLayers.Layer.Vector("myroads", {
+            strategies: [new OpenLayers.Strategy.BBOX()],
+            protocol: new OpenLayers.Protocol.WFS({
+                url:  "http://foo/wfs",
+                featureType: "roads",
+                featureNS: "http://foo/myns"
+            })
+        });
+        map.addLayers([layer, wfs]);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var owc = new OpenLayers.Format.OWSContext();
+        var output = owc.write(map, {id: 'foo'});
+        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer name="feature:roads" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">myroads</ows:Title><Server version="1.0.0" service="urn:ogc:serviceType:WFS"><OnlineResource xlink:href="http://foo/wfs" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
+        t.xml_eq(output, expected, "OWSContext with a WMS and a WFS layer generated correctly");
+    }
+
+    function test_write_wmsinlinegml(t) {
+        t.plan(1);
+        var lon = 5;
+        var lat = 40;
+        var zoom = 5;
+        var map = new OpenLayers.Map( 'map' );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://labs.metacarta.com/wms/vmap0",
+            {layers: 'basic'},
+            {singleTile: true}
+        );
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var vector = new OpenLayers.Layer.Vector();
+        map.addLayer(vector);
+        var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,1));
+        var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,0));
+        vector.addFeatures(feature1);
+        vector.addFeatures(feature2);
+        var owc = new OpenLayers.Format.OWSContext();
+        var output = owc.write(map, {id: 'foo'});
+        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer name="vector" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows"/><InlineGeometry><gml:boundedBy xmlns:gml="http://www.opengis.net/gml"><gml:Box><gml:coordinates decimal="." cs="," ts=" ">0,0 1,1</gml:coordinates></gml:Box></gml:boundedBy><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:vector xmlns:feature="http://mapserver.gis.umn.edu/mapserver"><feature:geometry><gml:Point><gml:coordinates decimal="." cs="," ts=" ">0,1</gml:coordinates></gml:Point></feature:geometry></feature:vector></gml:featureMember><gml:featureMember xmlns:gml="http://www.opengis.net/gml"><feature:vector xmlns:feature="http://mapserver.gis.umn.edu/mapserver"><feature:geometry><gml:Point><gml:coordinates decimal="." cs="," ts=" ">1,0</gml:coordinates></gml:Point></feature:geometry></feature:vector></gml:featureMember></InlineGeometry></Layer></ResourceList></OWSContext>';
+        t.xml_eq(output, expected, "OWSContext with a WMS and an inline GML vector layer generated correctly");
+    }
+
+    function test_read_inline(t) {
+        t.plan(10);
+        var text = '<?xml version="1.0" encoding="UTF-8"?><OWSContext xmlns="http://www.opengis.net/ows-context" xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.3.1" id="ows-context-ex-1-v3" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.0/owsContext.xsd"><General><ows:BoundingBox crs="urn:ogc:def:crs:EPSG:6.6:4326"><ows:LowerCorner>-117.44667178362664 32.57086210449395</ows:LowerCorner><ows:UpperCorner>-116.74066794885977 32.921986352104064</ows:UpperCorner></ows:BoundingBox><ows:Title>OWS Context version 0.3.0 Inline KML and GML examples</ows:Title></General><ResourceList><!-- WMS Example --><Layer name="topp:major_roads" queryable="1" hidden="1">	<ows:Title>Tiger 2005f
 e major roads</ows:Title>	<ows:OutputFormat>image/png</ows:OutputFormat><Server service="urn:ogc:serviceType:WMS" version="1.1.1"><OnlineResource xlink:href="http://sigma.openplans.org:8080/geoserver/wms?SERVICE=WMS"/></Server></Layer><!-- Inline KML Example --><Layer name="archsites"><ows:Title>Architectural Sites</ows:Title><kml:Document><kml:name>opengeo:archsites 1 to 100</kml:name><kml:Style id="archsitesStyle"><kml:IconStyle><kml:color>ffffffff</kml:color><kml:colorMode>normal</kml:colorMode><kml:Icon><kml:href>http://maps.google.com/mapfiles/kml/pal4/icon25.png</kml:href></kml:Icon></kml:IconStyle></kml:Style><kml:Placemark id="archsites.1"><kml:name>Signature Rock</kml:name><kml:description>Signature Rock Description</kml:description><kml:styleUrl>#archsitesStyle</kml:styleUrl><kml:Point><kml:coordinates>-103.82681673,44.38162255</kml:coordinates></kml:Point></kml:Placemark></kml:Document></Layer><!-- Inline GML Example --><Layer name="coastg"><ows:Title>Coastg as GM
 L Points</ows:Title><InlineGeometry><gml:boundedBy><gml:Box><gml:coord><gml:X>-43.379</gml:X><gml:Y>72.746</gml:Y></gml:coord><gml:coord><gml:X>-43.390</gml:X><gml:Y>72.755</gml:Y></gml:coord></gml:Box></gml:boundedBy><gml:featureMember><au1:coastg xmlns:au1="http://www.ionicsoft.com/wfs" fid="coastg.0"><au1:MERGE>1</au1:MERGE><au1:AREA>0.0020000000000000005</au1:AREA><au1:PERIMETER>0.167</au1:PERIMETER><au1:GEOMETRY><gml:Polygon srsName="urn:ogc:def:crs:EPSG:6.6:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>129.29167335893825,71.9583353847737 129.29167335893825,72.0000014248896 129.33332733905414,72.0000014248896 129.33332733905414,71.9583353847737 129.29167335893825,71.9583353847737</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></au1:GEOMETRY></au1:coastg></gml:featureMember><gml:featureMember><au1:coastg xmlns:au1="http://www.ionicsoft.com/wfs" fid="coastg.1"><au1:MERGE>1</au1:MERGE><au1:AREA>0.0020000000000000005</au1:AREA><au1:PERIM
 ETER>0.167</au1:PERIMETER><au1:GEOMETRY><gml:Polygon srsName="urn:ogc:def:crs:EPSG:6.6:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>135.45832829609282,35.66666796381659 135.41667179597695,35.66666796381659 135.41667179597695,35.70833202393249 135.45832829609282,35.70833202393249 135.45832829609282,35.66666796381659</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></au1:GEOMETRY></au1:coastg></gml:featureMember></InlineGeometry></Layer></ResourceList></OWSContext>';
+        var parser = new OpenLayers.Format.OWSContext();
+        var context = parser.read(text, {map: 'map'});
+        t.ok(context.layers[1] instanceof OpenLayers.Layer.Vector, "Inline KML results in a vector layer");
+        t.eq(context.layers[1].features.length, 1, "Inline KML layer has one feature");
+        t.ok(context.layers[1].features[0].geometry instanceof OpenLayers.Geometry.Point, "KML feature is a point");
+        t.eq(context.layers[1].features[0].attributes.description, "Signature Rock Description", "KML Description correctly parsed");
+        t.eq(context.layers[1].features[0].fid, "archsites.1", "KML feature id correctly parsed");
+        t.eq(context.layers[1].features[0].style.externalGraphic, "http://maps.google.com/mapfiles/kml/pal4/icon25.png", "Style url for KML feature correctly parsed");
+        t.ok(context.layers[2] instanceof OpenLayers.Layer.Vector, "Inline GML results in a vector layer");
+        t.eq(context.layers[2].features.length, 2, "Inline GML layer has two features");
+        t.ok(context.layers[2].features[0].geometry instanceof OpenLayers.Geometry.Polygon, "GML feature is a polygon");
+        t.eq(context.layers[2].features[0].attributes.MERGE, "1", "GML attribute read correctly");
+    }
+
+    function test_read_gml(t) {
+        t.plan(5);
+        var text = '<?xml version="1.0" encoding="UTF-8"?><OWSContext version="0.3.0" id="ows-context-ex-1-v3" xmlns="http://www.opengis.net/ows-context" xmlns:gml="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.0/owsContext.xsd"><General><ows:BoundingBox crs="urn:ogc:def:crs:EPSG:6.6:4326"><ows:LowerCorner>-117.44667178362664 32.57086210449395</ows:LowerCorner><ows:UpperCorner>-116.74066794885977 32.921986352104064</ows:UpperCorner></ows:BoundingBox><ows:Title>OWS Context version 0.3.0 examples</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0" opacity="1"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers 
 WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer><!-- Referenced GML Example --><Layer name="Landuse"><ows:Title>Boston Landuse Polygons</ows:Title><Server service="urn:ogc:serviceType:GML" version="2.1.2" title="Cadcorp GeognoSIS.NET Web Feature Service"><OnlineResource xlink:href="http://www.cadcorpdev.co.uk/gml/MassGIS/LandUse.gml"/></Server><sld:MinScaleDenominator>5000</sld:MinScaleDenominator><sld:MaxScaleDenominator>50000</sld:MaxScaleDenominator><MaxFeatures>99</MaxFeatures></Layer></ResourceList></OWSContext>';
+        var parser = new OpenLayers.Format.OWSContext();
+        var context = parser.read(text, {map: 'map'});
+        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.HTTP, "serviceType GML is translated into an HTTP Protocol");
+        t.eq(context.layers[1].protocol.url, "http://www.cadcorpdev.co.uk/gml/MassGIS/LandUse.gml", "Url of GML file correctly set");
+        t.ok(context.layers[1].protocol.format instanceof OpenLayers.Format.GML, "GML Format associated with protocol");
+        t.eq(Math.round(context.layers[1].minScale), 50000, "Minscale correctly read");
+        t.eq(Math.round(context.layers[1].maxScale), 5000, "Maxscale correctly read");
+    }
+
+    function test_read_kml(t) {
+        t.plan(3);
+        var text = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 27.9150390625</ows:LowerCorner><ows:UpperCorner>15.986328125 52.0849609375</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0" opacity="1"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Serv
 er></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">KML</ows:Title><Server version="2.2" service="urn:ogc:serviceType:KML"><OnlineResource xlink:href="http://foo/sundials.kml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
+        var parser = new OpenLayers.Format.OWSContext();
+        var context = parser.read(text, {map: 'map'});
+        t.ok(context.layers[1].protocol instanceof OpenLayers.Protocol.HTTP, "serviceType KML is translated into an HTTP Protocol");
+        t.eq(context.layers[1].protocol.url, "http://foo/sundials.kml", "Url of KML file correctly set");
+        t.ok(context.layers[1].protocol.format instanceof OpenLayers.Format.KML, "KML Format associated with protocol");
+    }
+
+    function test_write_gml(t) {
+        t.plan(1);
+        var lon = 5;
+        var lat = 40;
+        var zoom = 5;
+        var map = new OpenLayers.Map( 'map' );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://labs.metacarta.com/wms/vmap0",
+            {layers: 'basic'},
+            {singleTile: true}
+        );
+        var sundials = new OpenLayers.Layer.Vector("GML", {
+            projection: map.displayProjection,
+            strategies: [new OpenLayers.Strategy.Fixed()],
+            protocol: new OpenLayers.Protocol.HTTP({
+                url: "http://foo/sundials.gml",
+                format: new OpenLayers.Format.GML()
+            })
+        });
+        map.addLayers([layer, sundials]);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var owc = new OpenLayers.Format.OWSContext();
+        var output = owc.write(map, {id: 'foo'});
+        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">GML</ows:Title><Server version="2.1.2" service="urn:ogc:serviceType:GML"><OnlineResource xlink:href="http://foo/sundials.gml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
+        t.xml_eq(output, expected, "OWSContext with a WMS and a GML vector layer generated correctly");
+    }
+
+    function test_write_kml(t) {
+        t.plan(1);
+        var lon = 5;
+        var lat = 40;
+        var zoom = 5;
+        var map = new OpenLayers.Map( 'map' );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://labs.metacarta.com/wms/vmap0",
+            {layers: 'basic'},
+            {singleTile: true}
+        );
+        var sundials = new OpenLayers.Layer.Vector("KML", {
+            projection: map.displayProjection,
+            strategies: [new OpenLayers.Strategy.Fixed()],
+            protocol: new OpenLayers.Protocol.HTTP({
+                url: "http://foo/sundials.kml",
+                format: new OpenLayers.Format.KML({
+                    extractStyles: true
+                })
+            })
+        });
+        map.addLayers([layer, sundials]);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var owc = new OpenLayers.Format.OWSContext();
+        var output = owc.write(map, {id: 'foo'});
+        var expected = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="foo" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-5.986328125 29.013671875</ows:LowerCorner><ows:UpperCorner>15.986328125 50.986328125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer name="basic" queryable="0" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers WMS</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://labs.metacarta.com/wms/vmap0" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer
 ><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">KML</ows:Title><Server version="2.2" service="urn:ogc:serviceType:KML"><OnlineResource xlink:href="http://foo/sundials.kml" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></ResourceList></OWSContext>';
+        t.xml_eq(output, expected, "OWSContext with a WMS and a KML vector layer generated correctly");
+    }
+
+    function test_nested(t) {
+        t.plan(4);
+        var text = '<OWSContext xmlns="http://www.opengis.net/ows-context" version="0.3.1" id="machu" xsi:schemaLocation="http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="EPSG:4326"><ows:LowerCorner>-40 30</ows:LowerCorner><ows:UpperCorner>55 125</ows:UpperCorner></ows:BoundingBox><ows:Title xmlns:ows="http://www.opengis.net/ows">OpenLayers OWSContext</ows:Title></General><ResourceList><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">General Bathymetric Chart</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">GEBCO</ows:Title><Layer name="GEBCO" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">GEBCO</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/jpeg</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><Onlin
 eResource xlink:href="http://foo/bar_bathymetry?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/gebco.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Administrative boundaries</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">National boundaries</ows:Title><Layer name="GAUL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">GAUL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_topography?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource
  xlink:href="http://foo/services/geoservices/legends/machu/administrative_boundaries_land.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Maritime boundaries</ows:Title><Layer name="World_Maritime_Boundaries_v4_20090811" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">World_Maritime_Boundaries_v4_20090811</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_topography?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/administrative_boundaries_sea.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer
 ><ows:Title xmlns:ows="http://www.opengis.net/ows">Cultural Heritage Underwater</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Sites</ows:Title><Layer name="ARCH_NL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_NL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_nl?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_PL" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_PL</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat>
 <Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pl?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_PT" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_PT</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pt?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.o
 rg/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_BE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_BE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_be?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_SE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_SE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_se?" xml
 ns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_DE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">ARCH_DE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_de?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer><Layer name="ARCH_UK" queryable="1" hidden="0"><ows:T
 itle xmlns:ows="http://www.opengis.net/ows">ARCH_UK</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_uk?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server><StyleList><Style><Name>default</Name><Title>default</Title><LegendURL><OnlineResource xlink:href="http://foo/services/geoservices/legends/machu/cultural_heritage_underwater.png" xmlns:xlink="http://www.w3.org/1999/xlink"/></LegendURL></Style></StyleList></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Theme1</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">layer1</ows:Title><Layer name="TEST_AREA_BE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_BE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:s
 erviceType:WMS"><OnlineResource xlink:href="http://foo/bar_be?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer><Layer name="TEST_AREA_PT" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_PT</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_pt?" xmlns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></Layer></Layer><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">Theme2</ows:Title><Layer><ows:Title xmlns:ows="http://www.opengis.net/ows">layer1</ows:Title><Layer name="TEST_AREA_SE" queryable="1" hidden="0"><ows:Title xmlns:ows="http://www.opengis.net/ows">TEST_AREA_SE</ows:Title><ows:OutputFormat xmlns:ows="http://www.opengis.net/ows">image/png</ows:OutputFormat><Server version="1.1.1" service="urn:ogc:serviceType:WMS"><OnlineResource xlink:href="http://foo/bar_se?" xml
 ns:xlink="http://www.w3.org/1999/xlink"/></Server></Layer></Layer></Layer></ResourceList></OWSContext>';
+        var parser = new OpenLayers.Format.OWSContext();
+        var map = new OpenLayers.Map('map', {allOverlays: true, fractionalZoom: true});
+        var context = parser.read(text, {map: map});
+        t.eq(map.layers.length, 13, "13 layers parsed from document");
+        t.eq(map.layers[0].metadata.nestingPath.join("/"), "General Bathymetric Chart/GEBCO", "Category layers read correctly");
+        t.eq(map.layers[0].metadata.styles[0].legend.url, "http://foo/services/geoservices/legends/machu/gebco.png", "Legend url correctly parsed");
+        map.zoomToExtent(new OpenLayers.Bounds(-40, 30, 55, 125));
+        var owc = parser.write(map, {id: 'machu'});
+        t.xml_eq(text, owc, "Can we roundtrip nested OWSContext successfully?");
+    }
+
+    </script> 
+</head>
+<body>
+<div id="map" style="width:500px;height:500px"></div>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Format/SLD/v1_0_0.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/SLD/v1_0_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/SLD/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,6 +2,11 @@
 <head> 
     <script src="../../../lib/OpenLayers.js"></script>
     <script type="text/javascript">
+
+    var xml = new OpenLayers.Format.XML(); 
+    function readXML(id) {
+        return xml.read(document.getElementById(id).firstChild.nodeValue);
+    }
     
     var sld =
         '<StyledLayerDescriptor version="1.0.0" ' +
@@ -297,6 +302,36 @@
 
     }
     
+    
+    function test_writeLineSymbolizer(t) {
+
+        t.plan(1);
+
+        var parser = new OpenLayers.Format.SLD.v1_0_0();
+        var symbolizer, node, exp;
+        
+        // test symbolizer with fill color only
+        symbolizer = {
+            strokeDashstyle: "4 4",
+            strokeLinecap: "round",
+            strokeColor: "#0000ff",
+            strokeWidth: 2
+        };
+        node = parser.writeNode("sld:LineSymbolizer", symbolizer);
+        exp =
+            '<LineSymbolizer xmlns="http://www.opengis.net/sld">' +
+                '<Stroke>' +
+                    '<CssParameter name="stroke">#0000ff</CssParameter>' +
+                    '<CssParameter name="stroke-width">2</CssParameter>' +
+                    '<CssParameter name="stroke-dasharray">4 4</CssParameter>' +
+                    '<CssParameter name="stroke-linecap">round</CssParameter>' +
+                '</Stroke>' +
+            '</LineSymbolizer>';
+        t.xml_eq(node, exp, "line symbolizer correctly written");
+        
+
+    }
+    
     function test_writeTextSymbolizer(t) {
         t.plan(1);
         var parser = new OpenLayers.Format.SLD.v1_0_0();
@@ -377,11 +412,454 @@
         
         t.xml_eq(sld, expect, "rule with spatial filter correctly written");
         
+    }
+    
+    function test_RasterSymbolizer(t) {
+        t.plan(4);
         
+        var format = new OpenLayers.Format.SLD.v1_0_0();
+
+        var snippet =
+            '<sld:RasterSymbolizer xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc">' +
+                '<sld:Geometry>' +
+                    '<ogc:PropertyName>geom</ogc:PropertyName>' +
+                '</sld:Geometry>' +
+                '<sld:Opacity>1</sld:Opacity>' +
+                '<sld:ColorMap>' +
+                    '<sld:ColorMapEntry color="#000000" opacity="0.5" quantity="0" label="nodata"/>' +
+                    '<sld:ColorMapEntry color="#00FFFF" quantity="1" label="values"/>' +
+                    '<sld:ColorMapEntry color="#FF0000" quantity="1000" label="values"/>' +
+                '</sld:ColorMap>' +
+            '</sld:RasterSymbolizer>';
+        var expected = new OpenLayers.Format.XML().read(snippet).documentElement;
+    
+        var symbolizer = {};
+        format.readNode(expected, {symbolizer: symbolizer});
+        
+        t.eq(symbolizer.Raster.colorMap[0].quantity, 0, "quantity set correctly");
+        t.eq(symbolizer.Raster.colorMap[0].opacity, 0.5, "opacity set correctly");
+        t.eq(symbolizer.Raster.colorMap[1].opacity, undefined, "non-existent opacity results in undefined");
+        
+        var got = format.writeNode("sld:RasterSymbolizer", symbolizer["Raster"]);
+        
+        t.xml_eq(got, expected, "Successfully round tripped RasterSymbolizer");
     }
+    
+    function test_zIndex(t) {
+        t.plan(1);
+        
+        var format = new OpenLayers.Format.SLD.v1_0_0({
+            multipleSymbolizers: true
+        });
+        
+        // three zIndex values -> three FeatureTypeStyle elements
+        var style = new OpenLayers.Style2({
+            rules: [
+                new OpenLayers.Rule({
+                    filter: new OpenLayers.Filter.Comparison({
+                        type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                        property: "foo",
+                        value: "bar"
+                    }),
+                    minScaleDenominator: 100000,
+                    maxScaleDenominator: 200000,
+                    symbolizers: [
+                        new OpenLayers.Symbolizer.Line({
+                            strokeColor: "green",
+                            strokeWidth: 2,
+                            zIndex: 2
+                        }),
+                        new OpenLayers.Symbolizer.Line({
+                            strokeColor: "red",
+                            strokeWidth: 3,
+                            zIndex: -1
+                        }),
+                        new OpenLayers.Symbolizer.Line({
+                            strokeColor: "blue",
+                            strokeWidth: 1,
+                            zIndex: 5
+                        })
+                    ]
+                }),
+                new OpenLayers.Rule({
+                    filter: new OpenLayers.Filter.Comparison({
+                        type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                        property: "foo",
+                        value: "baz"
+                    }),                    
+                    symbolizers: [
+                        new OpenLayers.Symbolizer.Line({
+                            strokeColor: "#000000",
+                            strokeWidth: 2,
+                            zIndex: 2
+                        })
+                    ]
+                })
+            ]
+        });
+        
+        var got = format.writeNode("sld:UserStyle", style);
+        var exp = readXML("zindex_test.sld").documentElement;
+        t.xml_eq(got, exp, "duplicated rules to write zIndex as FeatureTypeStyle elements");
+        
+    }
+    
+    function test_read_FeatureTypeStyles(t) {
+        
+        t.plan(13);
+        
+        var format = new OpenLayers.Format.SLD.v1_0_0({
+            multipleSymbolizers: true,
+            namedLayersAsArray: true
+        });
+        var doc = readXML("line_linewithborder.sld");
+        
+        var obj = format.read(doc);
 
+        t.eq(obj.namedLayers.length, 1, "got one named layer");
+        var namedLayer = obj.namedLayers[0];
+        
+        t.eq(namedLayer.userStyles.length, 1, "got one user style");
+        var userStyle = namedLayer.userStyles[0];
+        t.ok(userStyle instanceof OpenLayers.Style2, "user style represented with OpenLayers.Style2");
+        
+        // check rules and symbolizers
+        var rule, symbolizer;
+        
+        t.eq(userStyle.rules.length, 2, "pulled two rules (from two FeatureTypeStyle elements)");
+        rule = userStyle.rules[0];
+        t.ok(rule instanceof OpenLayers.Rule, "first rule is an OpenLayers.Rule");
+        
+        t.eq(rule.symbolizers && rule.symbolizers.length, 1, "first rule has one symbolizer");
+        symbolizer = rule.symbolizers[0];
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "first symbolizer in first rule is an OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Line, "first symbolizer in first rule is an OpenLayers.Symbolizer.Line");
+        t.eq(symbolizer.zIndex, 0, "symbolizer from first FeatureTypeStyle element has zIndex 0");
+        
+        rule = userStyle.rules[1];
+        t.eq(rule.symbolizers && rule.symbolizers.length, 1, "second rule has one symbolizer");
+        symbolizer = rule.symbolizers[0];
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "first symbolizer in second rule is an OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Line, "first symbolizer in second rule is an OpenLayers.Symbolizer.Line");
+        t.eq(symbolizer.zIndex, 1, "symbolizer from second FeatureTypeStyle element has zIndex 1");
+        
+    }
+
+    function test_roundtrip(t) {
+        
+        t.plan(5);
+        
+        var format = new OpenLayers.Format.SLD.v1_0_0({
+            multipleSymbolizers: true,
+            namedLayersAsArray: true
+        });
+        var doc, out;
+        
+        // two FeatureTypeStyle elements and line symbolizers
+        doc = readXML("line_linewithborder.sld");
+        out = format.write(format.read(doc));
+        t.xml_eq(out, doc.documentElement, "round-tripped line_linewithborder.sld");
+
+        // three FeatureTypeStyle elements and line symbolizers
+        doc = readXML("line_attributebasedline.sld");
+        out = format.write(format.read(doc));
+        t.xml_eq(out, doc.documentElement, "round-tripped line_attributebasedline.sld");
+        
+        // point symbolizer and text symbolizer
+        doc = readXML("point_pointwithdefaultlabel.sld");
+        out = format.write(format.read(doc));
+        t.xml_eq(out, doc.documentElement, "round-tripped point_pointwithdefaultlabel.sld");
+        
+        // polygon symbolizer with fill only 
+        doc = readXML("polygon_simplepolygon.sld");
+        out = format.write(format.read(doc));
+        t.xml_eq(out, doc.documentElement, "round-tripped polygon_simplepolygon.sld");
+
+        // polygon symbolizer and text symbolizer with halo
+        doc = readXML("polygon_labelhalo.sld");
+        out = format.write(format.read(doc));
+        t.xml_eq(out, doc.documentElement, "round-tripped polygon_labelhalo.sld");
+
+    }
+
     </script> 
 </head> 
 <body>
+<div id="line_linewithborder.sld"><!--
+<StyledLayerDescriptor version="1.0.0" 
+    xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" 
+    xmlns="http://www.opengis.net/sld" 
+    xmlns:ogc="http://www.opengis.net/ogc" 
+    xmlns:xlink="http://www.w3.org/1999/xlink" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <NamedLayer>
+    <Name>Line with border</Name>
+    <UserStyle>
+    <Title>SLD Cook Book: Line w2th border</Title>
+      <FeatureTypeStyle>
+         <Rule>
+          <LineSymbolizer>
+            <Stroke>
+              <CssParameter name="stroke">#333333</CssParameter>                           
+              <CssParameter name="stroke-width">5</CssParameter>    
+              <CssParameter name="stroke-linecap">round</CssParameter>    
+            </Stroke> 
+          </LineSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+      <FeatureTypeStyle>
+         <Rule>
+          <LineSymbolizer>
+          <Stroke>
+              <CssParameter name="stroke">#6699FF</CssParameter>                           
+              <CssParameter name="stroke-width">3</CssParameter> 
+              <CssParameter name="stroke-linecap">round</CssParameter>  
+            </Stroke>
+          </LineSymbolizer>                                          
+         </Rule>
+      </FeatureTypeStyle>
+    </UserStyle>
+  </NamedLayer>
+</StyledLayerDescriptor>
+--></div>
+<div id="line_attributebasedline.sld"><!--
+<StyledLayerDescriptor version="1.0.0" 
+    xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" 
+    xmlns="http://www.opengis.net/sld" 
+    xmlns:ogc="http://www.opengis.net/ogc" 
+    xmlns:xlink="http://www.w3.org/1999/xlink" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <NamedLayer>
+    <Name>Attribute-based line</Name>
+    <UserStyle>
+      <Title>SLD Cook Book: Attribute-based line</Title>
+      <FeatureTypeStyle>
+        <Rule>
+          <Name>local-road</Name>
+          <ogc:Filter>
+            <ogc:PropertyIsEqualTo>
+              <ogc:PropertyName>type</ogc:PropertyName>
+              <ogc:Literal>local-road</ogc:Literal>
+            </ogc:PropertyIsEqualTo>
+          </ogc:Filter>
+          <LineSymbolizer>
+            <Stroke>
+              <CssParameter name="stroke">#009933</CssParameter>
+              <CssParameter name="stroke-width">2</CssParameter>
+            </Stroke>
+          </LineSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+      <FeatureTypeStyle>
+        <Rule>
+          <Name>secondary</Name>
+          <ogc:Filter>
+            <ogc:PropertyIsEqualTo>
+              <ogc:PropertyName>type</ogc:PropertyName>
+              <ogc:Literal>secondary</ogc:Literal>
+            </ogc:PropertyIsEqualTo>
+          </ogc:Filter>
+          <LineSymbolizer>
+            <Stroke>
+              <CssParameter name="stroke">#0055CC</CssParameter>
+              <CssParameter name="stroke-width">3</CssParameter>
+            </Stroke>
+          </LineSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+      <FeatureTypeStyle>
+        <Rule>
+        <Name>highway</Name>
+          <ogc:Filter>
+            <ogc:PropertyIsEqualTo>
+              <ogc:PropertyName>type</ogc:PropertyName>
+              <ogc:Literal>highway</ogc:Literal>
+            </ogc:PropertyIsEqualTo>
+          </ogc:Filter>
+          <LineSymbolizer>
+            <Stroke>
+              <CssParameter name="stroke">#FF0000</CssParameter>
+              <CssParameter name="stroke-width">6</CssParameter>
+            </Stroke>
+          </LineSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+    </UserStyle>
+  </NamedLayer>
+</StyledLayerDescriptor> 
+--></div>
+<div id="point_pointwithdefaultlabel.sld"><!--
+<StyledLayerDescriptor version="1.0.0" 
+    xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" 
+    xmlns="http://www.opengis.net/sld" 
+    xmlns:ogc="http://www.opengis.net/ogc" 
+    xmlns:xlink="http://www.w3.org/1999/xlink" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <NamedLayer>
+    <Name>Point with default label</Name>
+    <UserStyle>
+      <Title>GeoServer SLD Cook Book: Point with default label</Title>
+      <FeatureTypeStyle>
+        <Rule>
+          <PointSymbolizer>
+            <Graphic>
+              <Mark>
+                <WellKnownName>circle</WellKnownName>
+                <Fill>
+                  <CssParameter name="fill">#FF0000</CssParameter>
+                </Fill>
+              </Mark>
+              <Size>6</Size>
+            </Graphic>
+          </PointSymbolizer>
+          <TextSymbolizer>
+            <Label>
+              <ogc:PropertyName>name</ogc:PropertyName>
+            </Label>
+            <Fill>
+              <CssParameter name="fill">#000000</CssParameter>
+            </Fill>
+          </TextSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+    </UserStyle>
+  </NamedLayer>
+</StyledLayerDescriptor>
+--></div>
+<div id="polygon_simplepolygon.sld"><!--
+<StyledLayerDescriptor version="1.0.0" 
+    xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" 
+    xmlns="http://www.opengis.net/sld" 
+    xmlns:ogc="http://www.opengis.net/ogc" 
+    xmlns:xlink="http://www.w3.org/1999/xlink" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <NamedLayer>
+    <Name>Simple polygon</Name>
+    <UserStyle>
+      <Title>SLD Cook Book: Simple polygon</Title>
+      <FeatureTypeStyle>
+        <Rule>
+          <PolygonSymbolizer>
+            <Fill>
+              <CssParameter name="fill">#000080</CssParameter>
+            </Fill>
+          </PolygonSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+    </UserStyle>
+  </NamedLayer>
+</StyledLayerDescriptor>
+--></div>
+<div id="polygon_labelhalo.sld"><!--
+<StyledLayerDescriptor version="1.0.0" 
+    xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd" 
+    xmlns="http://www.opengis.net/sld" 
+    xmlns:ogc="http://www.opengis.net/ogc" 
+    xmlns:xlink="http://www.w3.org/1999/xlink" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <NamedLayer>
+    <Name>Label halo</Name>
+    <UserStyle>
+      <Title>SLD Cook Book: Label halo</Title>
+      <FeatureTypeStyle>
+        <Rule>
+          <PolygonSymbolizer>
+            <Fill>
+              <CssParameter name="fill">#40FF40</CssParameter>
+            </Fill>
+            <Stroke>
+              <CssParameter name="stroke">#FFFFFF</CssParameter>
+              <CssParameter name="stroke-width">2</CssParameter>
+            </Stroke>
+          </PolygonSymbolizer>        
+          <TextSymbolizer>
+            <Label>
+              <ogc:PropertyName>name</ogc:PropertyName>
+            </Label>
+            <Halo>
+              <Radius>3</Radius>
+              <Fill>
+                <CssParameter name="fill">#FFFFFF</CssParameter>
+              </Fill>
+            </Halo>
+          </TextSymbolizer>
+        </Rule>
+      </FeatureTypeStyle>
+    </UserStyle>
+  </NamedLayer>
+</StyledLayerDescriptor>
+--></div>
+<div id="zindex_test.sld"><!--
+<sld:UserStyle xmlns:sld="http://www.opengis.net/sld">
+    <sld:FeatureTypeStyle>
+        <sld:Rule>
+            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+                <ogc:PropertyIsEqualTo>
+                    <ogc:PropertyName>foo</ogc:PropertyName>
+                    <ogc:Literal>bar</ogc:Literal>
+                </ogc:PropertyIsEqualTo>
+            </ogc:Filter>
+            <sld:MinScaleDenominator>100000</sld:MinScaleDenominator>
+            <sld:MaxScaleDenominator>200000</sld:MaxScaleDenominator>
+            <sld:LineSymbolizer>
+                <sld:Stroke>
+                    <sld:CssParameter name="stroke">red</sld:CssParameter>
+                    <sld:CssParameter name="stroke-width">3</sld:CssParameter>
+                </sld:Stroke>
+            </sld:LineSymbolizer>
+        </sld:Rule>
+    </sld:FeatureTypeStyle>
+    <sld:FeatureTypeStyle>
+        <sld:Rule>
+            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+                <ogc:PropertyIsEqualTo>
+                    <ogc:PropertyName>foo</ogc:PropertyName>
+                    <ogc:Literal>bar</ogc:Literal>
+                </ogc:PropertyIsEqualTo>
+            </ogc:Filter>
+            <sld:MinScaleDenominator>100000</sld:MinScaleDenominator>
+            <sld:MaxScaleDenominator>200000</sld:MaxScaleDenominator>
+            <sld:LineSymbolizer>
+                <sld:Stroke>
+                    <sld:CssParameter name="stroke">green</sld:CssParameter>
+                    <sld:CssParameter name="stroke-width">2</sld:CssParameter>
+                </sld:Stroke>
+            </sld:LineSymbolizer>
+        </sld:Rule>
+        <sld:Rule>
+            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+                <ogc:PropertyIsEqualTo>
+                    <ogc:PropertyName>foo</ogc:PropertyName>
+                    <ogc:Literal>baz</ogc:Literal>
+                </ogc:PropertyIsEqualTo>
+            </ogc:Filter>
+            <sld:LineSymbolizer>
+                <sld:Stroke>
+                    <sld:CssParameter name="stroke">#000000</sld:CssParameter>
+                    <sld:CssParameter name="stroke-width">2</sld:CssParameter>
+                </sld:Stroke>
+            </sld:LineSymbolizer>
+        </sld:Rule>
+    </sld:FeatureTypeStyle>
+    <sld:FeatureTypeStyle>
+        <sld:Rule>
+            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+                <ogc:PropertyIsEqualTo>
+                    <ogc:PropertyName>foo</ogc:PropertyName>
+                    <ogc:Literal>bar</ogc:Literal>
+                </ogc:PropertyIsEqualTo>
+            </ogc:Filter>
+            <sld:MinScaleDenominator>100000</sld:MinScaleDenominator>
+            <sld:MaxScaleDenominator>200000</sld:MaxScaleDenominator>
+            <sld:LineSymbolizer>
+                <sld:Stroke>
+                    <sld:CssParameter name="stroke">blue</sld:CssParameter>
+                    <sld:CssParameter name="stroke-width">1</sld:CssParameter>
+                </sld:Stroke>
+            </sld:LineSymbolizer>
+        </sld:Rule>
+    </sld:FeatureTypeStyle>
+</sld:UserStyle>
+--></div>
 </body> 
 </html> 

Deleted: sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html
===================================================================
--- trunk/openlayers/tests/Format/SOSCapabilities/v1_0_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,80 +0,0 @@
-<html>
-<head>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script src="v1_0_0.js"></script>
-    <script type="text/javascript">
-
-    function test_read(t) {
-
-        t.plan(41);
-
-        var format = new OpenLayers.Format.SOSCapabilities();
-        var obj = format.read(doc);
-
-        t.eq(obj.version, "1.0.0", "Version parsed correctly");
-
-        // service identification (from OWSCommon)
-        t.eq(obj.serviceIdentification.abstract, "WeatherSOS (stable) at IfGI, Muenster, Germany. For more info: http://ifgipedia.uni-muenster.de/kms/documentation/swsl/sos/", "Abstract parsed correctly");
-        t.eq(obj.serviceIdentification.accessConstraints, "NONE", "AccessConstraints parsed correctly");
-        t.eq(obj.serviceIdentification.fees, "NONE", "Fees parsed correctly");
-        for (var key in obj.serviceIdentification.keywords) {
-            t.eq(key, "rain gauge, radiation, pressure, windspeed, winddirection, temperature", "Keywords parsed correctly");
-        }
-        t.eq(obj.serviceIdentification.serviceType.codeSpace, "http://opengeospatial.net", "codeSpace correctly parsed");
-        t.eq(obj.serviceIdentification.serviceType.value, "OGC:SOS", "ServiceType correctly parsed");
-        t.eq(obj.serviceIdentification.serviceTypeVersion, "1.0.0", "ServiceTypeVersion correctly parsed");
-        t.eq(obj.serviceIdentification.title, "IFGI WeatherSOS (stable)", "Title correctly parsed");
-
-        // service provider (from OWSCommon)
-        t.eq(obj.serviceProvider.providerName, "Institute for Geoinformatics, University of Muenster", "ProviderName correctly parsed");
-        t.eq(obj.serviceProvider.providerSite, "http://ifgi.uni-muenster.de", "ProviderSite correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.individualName, "Eike Hinderk Juerrens", "IndividualName parsed correctly");
-        t.eq(obj.serviceProvider.serviceContact.positionName, "Student Associate", "PositionName parsed correctly");
-        t.eq(obj.serviceProvider.serviceContact.role, "", "Role parsed correctly");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.administrativeArea, "NRW", "AdministrativeArea correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.city, "Muenster", "City correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.country, "Germany", "Country correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.deliveryPoint, "Weselerstrasse 253", "DeliveryPoint correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.electronicMailAddress, "ehjuerrens at uni-muenster.de", "ElectronicMailAddress correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.postalCode, "48149", "Postalcode correctly parsed");
-        t.eq(obj.serviceProvider.serviceContact.contactInfo.phone.voice, "+49-251-83-30088", "Voice phone correctly parsed");
-
-        // operationsMetadata (from OWSCommon)
-        t.eq(obj.operationsMetadata.DescribeSensor.dcp.http.post, "http://v-swe.uni-muenster.de:8080/WeatherSOS/sos", "POST url for DescribeSensor correctly parsed");
-        var counter = 0;
-        for (var key in obj.operationsMetadata.DescribeSensor.parameters.procedure.allowedValues) {
-            if (counter == 0) {
-                t.eq(key, "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (1) for procedure parameter in DescribeSensor request correctly parsed");
-            } else if (counter == 1) {
-                t.eq(key, "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (2) for procedure parameter in DescribeSensor request correctly parsed");
-            }
-            counter++;
-        }
-        t.eq(obj.operationsMetadata.GetFeatureOfInterest.parameters.location.anyValue, true, "AnyValue parsed correctly");
-
-        t.eq(obj.operationsMetadata.GetObservation.parameters.eventTime.allowedValues.range.maxValue, "2009-11-04T14:45:00+01", "Range maxValue parsed correctly");
-        t.eq(obj.operationsMetadata.GetObservation.parameters.eventTime.allowedValues.range.minValue, "2008-02-14T11:03:02+01", "Range minValue parsed correctly");
-
-        // Contents (from SOS)
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.name, "Pressure of the atmosphere", "Name of offering correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.observedProperties[0], "urn:x-ogc:def:property:OGC::BarometricPressure", "ObservedProperty correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.featureOfInterestIds[0], "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (1) for featureOfInterest correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.featureOfInterestIds[1], "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (2) for featureOfInterest correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.procedures[0], "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (1) for procedures correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.procedures[1], "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (2) for procedures correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseFormats[0], 'text/xml;subtype="om/1.0.0"', "Allowed value (1) for responseFormats correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseFormats[1], "application/zip", "Allowed value (2) for responseFormats correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseModes[0], "inline", "Allowed value (1) for responseModes correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseModes[1], "resultTemplate", "Allowed value (2) for responseModes correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.resultModels[0], "ns:Measurement", "Allowed value (1) for resultModels correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.resultModels[1], "ns:Observation", "Allowed value (2) for resultModels correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.time.timePeriod.beginPosition, "2008-12-20T02:29:27+01:00", "TimePeriod beginPosition correctly parsed");
-        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.time.timePeriod.endPosition, "2009-11-04T14:45:00+01:00", "TimePeriod endPosition correctly parsed");
-
-    }
-
-    </script>
-</head>
-<body>
-</body>
-</html>

Copied: sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html (from rev 10919, trunk/openlayers/tests/Format/SOSCapabilities/v1_0_0.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script src="v1_0_0.js"></script>
+    <script type="text/javascript">
+
+    function test_read(t) {
+
+        t.plan(41);
+
+        var format = new OpenLayers.Format.SOSCapabilities();
+        var obj = format.read(doc);
+
+        t.eq(obj.version, "1.0.0", "Version parsed correctly");
+
+        // service identification (from OWSCommon)
+        t.eq(obj.serviceIdentification.abstract, "WeatherSOS (stable) at IfGI, Muenster, Germany. For more info: http://ifgipedia.uni-muenster.de/kms/documentation/swsl/sos/", "Abstract parsed correctly");
+        t.eq(obj.serviceIdentification.accessConstraints, "NONE", "AccessConstraints parsed correctly");
+        t.eq(obj.serviceIdentification.fees, "NONE", "Fees parsed correctly");
+        for (var key in obj.serviceIdentification.keywords) {
+            t.eq(key, "rain gauge, radiation, pressure, windspeed, winddirection, temperature", "Keywords parsed correctly");
+        }
+        t.eq(obj.serviceIdentification.serviceType.codeSpace, "http://opengeospatial.net", "codeSpace correctly parsed");
+        t.eq(obj.serviceIdentification.serviceType.value, "OGC:SOS", "ServiceType correctly parsed");
+        t.eq(obj.serviceIdentification.serviceTypeVersion, "1.0.0", "ServiceTypeVersion correctly parsed");
+        t.eq(obj.serviceIdentification.title, "IFGI WeatherSOS (stable)", "Title correctly parsed");
+
+        // service provider (from OWSCommon)
+        t.eq(obj.serviceProvider.providerName, "Institute for Geoinformatics, University of Muenster", "ProviderName correctly parsed");
+        t.eq(obj.serviceProvider.providerSite, "http://ifgi.uni-muenster.de", "ProviderSite correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.individualName, "Eike Hinderk Juerrens", "IndividualName parsed correctly");
+        t.eq(obj.serviceProvider.serviceContact.positionName, "Student Associate", "PositionName parsed correctly");
+        t.eq(obj.serviceProvider.serviceContact.role, "", "Role parsed correctly");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.administrativeArea, "NRW", "AdministrativeArea correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.city, "Muenster", "City correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.country, "Germany", "Country correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.deliveryPoint, "Weselerstrasse 253", "DeliveryPoint correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.electronicMailAddress, "ehjuerrens at uni-muenster.de", "ElectronicMailAddress correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.address.postalCode, "48149", "Postalcode correctly parsed");
+        t.eq(obj.serviceProvider.serviceContact.contactInfo.phone.voice, "+49-251-83-30088", "Voice phone correctly parsed");
+
+        // operationsMetadata (from OWSCommon)
+        t.eq(obj.operationsMetadata.DescribeSensor.dcp.http.post, "http://v-swe.uni-muenster.de:8080/WeatherSOS/sos", "POST url for DescribeSensor correctly parsed");
+        var counter = 0;
+        for (var key in obj.operationsMetadata.DescribeSensor.parameters.procedure.allowedValues) {
+            if (counter == 0) {
+                t.eq(key, "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (1) for procedure parameter in DescribeSensor request correctly parsed");
+            } else if (counter == 1) {
+                t.eq(key, "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (2) for procedure parameter in DescribeSensor request correctly parsed");
+            }
+            counter++;
+        }
+        t.eq(obj.operationsMetadata.GetFeatureOfInterest.parameters.location.anyValue, true, "AnyValue parsed correctly");
+
+        t.eq(obj.operationsMetadata.GetObservation.parameters.eventTime.allowedValues.range.maxValue, "2009-11-04T14:45:00+01", "Range maxValue parsed correctly");
+        t.eq(obj.operationsMetadata.GetObservation.parameters.eventTime.allowedValues.range.minValue, "2008-02-14T11:03:02+01", "Range minValue parsed correctly");
+
+        // Contents (from SOS)
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.name, "Pressure of the atmosphere", "Name of offering correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.observedProperties[0], "urn:x-ogc:def:property:OGC::BarometricPressure", "ObservedProperty correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.featureOfInterestIds[0], "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (1) for featureOfInterest correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.featureOfInterestIds[1], "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (2) for featureOfInterest correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.procedures[0], "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "Allowed value (1) for procedures correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.procedures[1], "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Allowed value (2) for procedures correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseFormats[0], 'text/xml;subtype="om/1.0.0"', "Allowed value (1) for responseFormats correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseFormats[1], "application/zip", "Allowed value (2) for responseFormats correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseModes[0], "inline", "Allowed value (1) for responseModes correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.responseModes[1], "resultTemplate", "Allowed value (2) for responseModes correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.resultModels[0], "ns:Measurement", "Allowed value (1) for resultModels correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.resultModels[1], "ns:Observation", "Allowed value (2) for resultModels correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.time.timePeriod.beginPosition, "2008-12-20T02:29:27+01:00", "TimePeriod beginPosition correctly parsed");
+        t.eq(obj.contents.offeringList.ATMOSPHERIC_PRESSURE.time.timePeriod.endPosition, "2009-11-04T14:45:00+01:00", "TimePeriod endPosition correctly parsed");
+
+    }
+
+    </script>
+</head>
+<body>
+</body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js
===================================================================
--- trunk/openlayers/tests/Format/SOSCapabilities/v1_0_0.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,484 +0,0 @@
-var doc = new OpenLayers.Format.XML().read(
-'<?xml version="1.0" encoding="UTF-8"?>' +
-'<sos:Capabilities version="1.0.0" updateSequence="2005-12-14T10:12:39+01" xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink">' +
-  '<ows:ServiceIdentification xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
-    '<ows:Title>IFGI WeatherSOS (stable)</ows:Title>' +
-    '<ows:Abstract>WeatherSOS (stable) at IfGI, Muenster, Germany. For more info: http://ifgipedia.uni-muenster.de/kms/documentation/swsl/sos/</ows:Abstract>' +
-    '<ows:Keywords>' +
-      '<ows:Keyword>rain gauge, radiation, pressure, windspeed, winddirection, temperature</ows:Keyword>' +
-    '</ows:Keywords>' +
-    '<ows:ServiceType codeSpace="http://opengeospatial.net">OGC:SOS</ows:ServiceType>' +
-    '<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>' +
-    '<ows:Fees>NONE</ows:Fees>' +
-    '<ows:AccessConstraints>NONE</ows:AccessConstraints>' +
-  '</ows:ServiceIdentification>' +
-  '<ows:ServiceProvider xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
-    '<ows:ProviderName>Institute for Geoinformatics, University of Muenster</ows:ProviderName>' +
-    '<ows:ProviderSite xlink:href="http://ifgi.uni-muenster.de"/>' +
-    '<ows:ServiceContact>' +
-      '<ows:IndividualName>Eike Hinderk Juerrens</ows:IndividualName>' +
-      '<ows:PositionName>Student Associate</ows:PositionName>' +
-      '<ows:ContactInfo>' +
-        '<ows:Phone>' +
-          '<ows:Voice>+49-251-83-30088</ows:Voice>' +
-        '</ows:Phone>' +
-        '<ows:Address>' +
-          '<ows:DeliveryPoint>Weselerstrasse 253</ows:DeliveryPoint>' +
-          '<ows:City>Muenster</ows:City>' +
-          '<ows:AdministrativeArea>NRW</ows:AdministrativeArea>' +
-          '<ows:PostalCode>48149</ows:PostalCode>' +
-          '<ows:Country>Germany</ows:Country>' +
-          '<ows:ElectronicMailAddress>ehjuerrens at uni-muenster.de</ows:ElectronicMailAddress>' +
-        '</ows:Address>' +
-      '</ows:ContactInfo>' +
-      '<ows:Role/>' +
-    '</ows:ServiceContact>' +
-  '</ows:ServiceProvider>' +
-  '<ows:OperationsMetadata xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
-    '<ows:Operation name="GetCapabilities">' +
-      '<ows:DCP>' +
-        '<ows:HTTP>' +
-          '<ows:Get xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos?"/>' +
-          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
-        '</ows:HTTP>' +
-      '</ows:DCP>' +
-      '<ows:Parameter name="service">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>SOS</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="updateSequence">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="AcceptVersions">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>1.0.0</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="Sections">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>ServiceIdentification</ows:Value>' +
-          '<ows:Value>ServiceProvider</ows:Value>' +
-          '<ows:Value>OperationsMetadata</ows:Value>' +
-          '<ows:Value>Contents</ows:Value>' +
-          '<ows:Value>All</ows:Value>' +
-          '<ows:Value>Filter_Capabilities</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="AcceptFormats">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>text/xml</ows:Value>' +
-          '<ows:Value>application/zip</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-    '</ows:Operation>' +
-    '<ows:Operation name="GetObservation">' +
-      '<ows:DCP>' +
-        '<ows:HTTP>' +
-          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
-        '</ows:HTTP>' +
-      '</ows:DCP>' +
-      '<ows:Parameter name="version">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>1.0.0</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="service">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>SOS</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="srsName">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="offering">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>ATMOSPHERIC_TEMPERATURE</ows:Value>' +
-          '<ows:Value>RAIN_GAUGE</ows:Value>' +
-          '<ows:Value>WIND_DIRECTION</ows:Value>' +
-          '<ows:Value>WIND_SPEED</ows:Value>' +
-          '<ows:Value>HUMIDITY</ows:Value>' +
-          '<ows:Value>LUMINANCE</ows:Value>' +
-          '<ows:Value>ATMOSPHERIC_PRESSURE</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="eventTime">' +
-        '<ows:AllowedValues>' +
-          '<ows:Range>' +
-            '<ows:MinimumValue>2008-02-14T11:03:02+01</ows:MinimumValue>' +
-            '<ows:MaximumValue>2009-11-04T14:45:00+01</ows:MaximumValue>' +
-          '</ows:Range>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="procedure">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="observedProperty">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::Temperature</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::Precipitation1Hour</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::WindDirection</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::WindSpeed</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::RelativeHumidity</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::Luminance</ows:Value>' +
-          '<ows:Value>urn:x-ogc:def:property:OGC::BarometricPressure</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="featureOfInterest">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="result">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="responseFormat">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>text/xml;subtype="OM/1.0.0"</ows:Value>' +
-          '<ows:Value>application/zip</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="resultModel">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>om:Observation</ows:Value>' +
-          '<ows:Value>om:CategoryObservation</ows:Value>' +
-          '<ows:Value>om:Measurement</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="responseMode">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>resultTemplate</ows:Value>' +
-          '<ows:Value>inline</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-    '</ows:Operation>' +
-    '<ows:Operation name="GetObservationById">' +
-      '<ows:DCP>' +
-        '<ows:HTTP>' +
-          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
-        '</ows:HTTP>' +
-      '</ows:DCP>' +
-      '<ows:Parameter name="version">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>1.0.0</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="service">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>SOS</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="srsName">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="ObservationId">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="responseFormat">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>text/xml;subtype="OM/1.0.0"</ows:Value>' +
-          '<ows:Value>application/zip</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="resultModel">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>om:Observation</ows:Value>' +
-          '<ows:Value>om:CategoryObservation</ows:Value>' +
-          '<ows:Value>om:Measurement</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="responseMode">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>inline</ows:Value>' +
-          '<ows:Value>resultTemplate</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-    '</ows:Operation>' +
-    '<ows:Operation name="DescribeSensor">' +
-      '<ows:DCP>' +
-        '<ows:HTTP>' +
-          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
-        '</ows:HTTP>' +
-      '</ows:DCP>' +
-      '<ows:Parameter name="version">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>1.0.0</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="service">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>SOS</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="outputFormat">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>text/xml;subtype="sensorML/1.0.1"</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="procedure">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-    '</ows:Operation>' +
-    '<ows:Operation name="GetFeatureOfInterest">' +
-      '<ows:DCP>' +
-        '<ows:HTTP>' +
-          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
-        '</ows:HTTP>' +
-      '</ows:DCP>' +
-      '<ows:Parameter name="service">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>SOS</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="version">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>1.0.0</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="featureOfInterestId">' +
-        '<ows:AllowedValues>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
-          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
-        '</ows:AllowedValues>' +
-      '</ows:Parameter>' +
-      '<ows:Parameter name="location">' +
-        '<ows:AnyValue/>' +
-      '</ows:Parameter>' +
-    '</ows:Operation>' +
-  '</ows:OperationsMetadata>' +
-  '<sos:Filter_Capabilities xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
-    '<ogc:Spatial_Capabilities>' +
-      '<ogc:GeometryOperands>' +
-        '<ogc:GeometryOperand>gml:Envelope</ogc:GeometryOperand>' +
-        '<ogc:GeometryOperand>gml:Polygon</ogc:GeometryOperand>' +
-        '<ogc:GeometryOperand>gml:Point</ogc:GeometryOperand>' +
-        '<ogc:GeometryOperand>gml:LineString</ogc:GeometryOperand>' +
-      '</ogc:GeometryOperands>' +
-      '<ogc:SpatialOperators>' +
-        '<ogc:SpatialOperator name="BBOX"/>' +
-        '<ogc:SpatialOperator name="Contains"/>' +
-        '<ogc:SpatialOperator name="Intersects"/>' +
-        '<ogc:SpatialOperator name="Overlaps"/>' +
-      '</ogc:SpatialOperators>' +
-    '</ogc:Spatial_Capabilities>' +
-    '<ogc:Temporal_Capabilities>' +
-      '<ogc:TemporalOperands>' +
-        '<ogc:TemporalOperand>gml:TimeInstant</ogc:TemporalOperand>' +
-        '<ogc:TemporalOperand>gml:TimePeriod</ogc:TemporalOperand>' +
-      '</ogc:TemporalOperands>' +
-      '<ogc:TemporalOperators>' +
-        '<ogc:TemporalOperator name="TM_During"/>' +
-        '<ogc:TemporalOperator name="TM_Equals"/>' +
-        '<ogc:TemporalOperator name="TM_After"/>' +
-        '<ogc:TemporalOperator name="TM_Before"/>' +
-      '</ogc:TemporalOperators>' +
-    '</ogc:Temporal_Capabilities>' +
-    '<ogc:Scalar_Capabilities>' +
-      '<ogc:ComparisonOperators>' +
-        '<ogc:ComparisonOperator>Between</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>LessThan</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>LessThanEqualTo</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>GreaterThan</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>GreaterThanEqualTo</ogc:ComparisonOperator>' +
-        '<ogc:ComparisonOperator>Like</ogc:ComparisonOperator>' +
-      '</ogc:ComparisonOperators>' +
-    '</ogc:Scalar_Capabilities>' +
-    '<ogc:Id_Capabilities>' +
-      '<ogc:FID/>' +
-      '<ogc:EID/>' +
-    '</ogc:Id_Capabilities>' +
-  '</sos:Filter_Capabilities>' +
-  '<sos:Contents>' +
-    '<sos:ObservationOfferingList>' +
-      '<sos:ObservationOffering gml:id="ATMOSPHERIC_TEMPERATURE">' +
-        '<gml:name>Temperature of the atmosphere</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Temperature"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="RAIN_GAUGE">' +
-        '<gml:name>Rain</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-11-20T15:35:22+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Precipitation1Hour"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="WIND_DIRECTION">' +
-        '<gml:name>Direction of the wind</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::WindDirection"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="WIND_SPEED">' +
-        '<gml:name>Speed of the wind</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::WindSpeed"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="HUMIDITY">' +
-        '<gml:name>Humidity of the atmosphere</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-02-14T11:03:02+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::RelativeHumidity"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="LUMINANCE">' +
-        '<gml:name>Luminance</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Luminance"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-      '<sos:ObservationOffering gml:id="ATMOSPHERIC_PRESSURE">' +
-        '<gml:name>Pressure of the atmosphere</gml:name>' +
-        '<gml:boundedBy>' +
-          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
-            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
-            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
-          '</gml:Envelope>' +
-        '</gml:boundedBy>' +
-        '<sos:time>' +
-          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
-            '<gml:beginPosition>2008-12-20T02:29:27+01:00</gml:beginPosition>' +
-            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
-          '</gml:TimePeriod>' +
-        '</sos:time>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::BarometricPressure"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
-        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
-        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
-        '<sos:responseFormat>application/zip</sos:responseFormat>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
-        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
-        '<sos:responseMode>inline</sos:responseMode>' +
-        '<sos:responseMode>resultTemplate</sos:responseMode>' +
-      '</sos:ObservationOffering>' +
-    '</sos:ObservationOfferingList>' +
-  '</sos:Contents>' +
-'</sos:Capabilities>'
-);
\ No newline at end of file

Copied: sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js (from rev 10919, trunk/openlayers/tests/Format/SOSCapabilities/v1_0_0.js)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/SOSCapabilities/v1_0_0.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,484 @@
+var doc = new OpenLayers.Format.XML().read(
+'<?xml version="1.0" encoding="UTF-8"?>' +
+'<sos:Capabilities version="1.0.0" updateSequence="2005-12-14T10:12:39+01" xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink">' +
+  '<ows:ServiceIdentification xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
+    '<ows:Title>IFGI WeatherSOS (stable)</ows:Title>' +
+    '<ows:Abstract>WeatherSOS (stable) at IfGI, Muenster, Germany. For more info: http://ifgipedia.uni-muenster.de/kms/documentation/swsl/sos/</ows:Abstract>' +
+    '<ows:Keywords>' +
+      '<ows:Keyword>rain gauge, radiation, pressure, windspeed, winddirection, temperature</ows:Keyword>' +
+    '</ows:Keywords>' +
+    '<ows:ServiceType codeSpace="http://opengeospatial.net">OGC:SOS</ows:ServiceType>' +
+    '<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>' +
+    '<ows:Fees>NONE</ows:Fees>' +
+    '<ows:AccessConstraints>NONE</ows:AccessConstraints>' +
+  '</ows:ServiceIdentification>' +
+  '<ows:ServiceProvider xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
+    '<ows:ProviderName>Institute for Geoinformatics, University of Muenster</ows:ProviderName>' +
+    '<ows:ProviderSite xlink:href="http://ifgi.uni-muenster.de"/>' +
+    '<ows:ServiceContact>' +
+      '<ows:IndividualName>Eike Hinderk Juerrens</ows:IndividualName>' +
+      '<ows:PositionName>Student Associate</ows:PositionName>' +
+      '<ows:ContactInfo>' +
+        '<ows:Phone>' +
+          '<ows:Voice>+49-251-83-30088</ows:Voice>' +
+        '</ows:Phone>' +
+        '<ows:Address>' +
+          '<ows:DeliveryPoint>Weselerstrasse 253</ows:DeliveryPoint>' +
+          '<ows:City>Muenster</ows:City>' +
+          '<ows:AdministrativeArea>NRW</ows:AdministrativeArea>' +
+          '<ows:PostalCode>48149</ows:PostalCode>' +
+          '<ows:Country>Germany</ows:Country>' +
+          '<ows:ElectronicMailAddress>ehjuerrens at uni-muenster.de</ows:ElectronicMailAddress>' +
+        '</ows:Address>' +
+      '</ows:ContactInfo>' +
+      '<ows:Role/>' +
+    '</ows:ServiceContact>' +
+  '</ows:ServiceProvider>' +
+  '<ows:OperationsMetadata xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
+    '<ows:Operation name="GetCapabilities">' +
+      '<ows:DCP>' +
+        '<ows:HTTP>' +
+          '<ows:Get xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos?"/>' +
+          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
+        '</ows:HTTP>' +
+      '</ows:DCP>' +
+      '<ows:Parameter name="service">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>SOS</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="updateSequence">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="AcceptVersions">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>1.0.0</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="Sections">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>ServiceIdentification</ows:Value>' +
+          '<ows:Value>ServiceProvider</ows:Value>' +
+          '<ows:Value>OperationsMetadata</ows:Value>' +
+          '<ows:Value>Contents</ows:Value>' +
+          '<ows:Value>All</ows:Value>' +
+          '<ows:Value>Filter_Capabilities</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="AcceptFormats">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>text/xml</ows:Value>' +
+          '<ows:Value>application/zip</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+    '</ows:Operation>' +
+    '<ows:Operation name="GetObservation">' +
+      '<ows:DCP>' +
+        '<ows:HTTP>' +
+          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
+        '</ows:HTTP>' +
+      '</ows:DCP>' +
+      '<ows:Parameter name="version">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>1.0.0</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="service">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>SOS</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="srsName">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="offering">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>ATMOSPHERIC_TEMPERATURE</ows:Value>' +
+          '<ows:Value>RAIN_GAUGE</ows:Value>' +
+          '<ows:Value>WIND_DIRECTION</ows:Value>' +
+          '<ows:Value>WIND_SPEED</ows:Value>' +
+          '<ows:Value>HUMIDITY</ows:Value>' +
+          '<ows:Value>LUMINANCE</ows:Value>' +
+          '<ows:Value>ATMOSPHERIC_PRESSURE</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="eventTime">' +
+        '<ows:AllowedValues>' +
+          '<ows:Range>' +
+            '<ows:MinimumValue>2008-02-14T11:03:02+01</ows:MinimumValue>' +
+            '<ows:MaximumValue>2009-11-04T14:45:00+01</ows:MaximumValue>' +
+          '</ows:Range>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="procedure">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="observedProperty">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::Temperature</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::Precipitation1Hour</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::WindDirection</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::WindSpeed</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::RelativeHumidity</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::Luminance</ows:Value>' +
+          '<ows:Value>urn:x-ogc:def:property:OGC::BarometricPressure</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="featureOfInterest">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="result">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="responseFormat">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>text/xml;subtype="OM/1.0.0"</ows:Value>' +
+          '<ows:Value>application/zip</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="resultModel">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>om:Observation</ows:Value>' +
+          '<ows:Value>om:CategoryObservation</ows:Value>' +
+          '<ows:Value>om:Measurement</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="responseMode">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>resultTemplate</ows:Value>' +
+          '<ows:Value>inline</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+    '</ows:Operation>' +
+    '<ows:Operation name="GetObservationById">' +
+      '<ows:DCP>' +
+        '<ows:HTTP>' +
+          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
+        '</ows:HTTP>' +
+      '</ows:DCP>' +
+      '<ows:Parameter name="version">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>1.0.0</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="service">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>SOS</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="srsName">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="ObservationId">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="responseFormat">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>text/xml;subtype="OM/1.0.0"</ows:Value>' +
+          '<ows:Value>application/zip</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="resultModel">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>om:Observation</ows:Value>' +
+          '<ows:Value>om:CategoryObservation</ows:Value>' +
+          '<ows:Value>om:Measurement</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="responseMode">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>inline</ows:Value>' +
+          '<ows:Value>resultTemplate</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+    '</ows:Operation>' +
+    '<ows:Operation name="DescribeSensor">' +
+      '<ows:DCP>' +
+        '<ows:HTTP>' +
+          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
+        '</ows:HTTP>' +
+      '</ows:DCP>' +
+      '<ows:Parameter name="version">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>1.0.0</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="service">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>SOS</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="outputFormat">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>text/xml;subtype="sensorML/1.0.1"</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="procedure">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+    '</ows:Operation>' +
+    '<ows:Operation name="GetFeatureOfInterest">' +
+      '<ows:DCP>' +
+        '<ows:HTTP>' +
+          '<ows:Post xlink:href="http://v-swe.uni-muenster.de:8080/WeatherSOS/sos"/>' +
+        '</ows:HTTP>' +
+      '</ows:DCP>' +
+      '<ows:Parameter name="service">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>SOS</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="version">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>1.0.0</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="featureOfInterestId">' +
+        '<ows:AllowedValues>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ows:Value>' +
+          '<ows:Value>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</ows:Value>' +
+        '</ows:AllowedValues>' +
+      '</ows:Parameter>' +
+      '<ows:Parameter name="location">' +
+        '<ows:AnyValue/>' +
+      '</ows:Parameter>' +
+    '</ows:Operation>' +
+  '</ows:OperationsMetadata>' +
+  '<sos:Filter_Capabilities xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:om="http://www.opengis.net/om/1.0" xmlns:swe="http://www.opengis.net/swe/1.0">' +
+    '<ogc:Spatial_Capabilities>' +
+      '<ogc:GeometryOperands>' +
+        '<ogc:GeometryOperand>gml:Envelope</ogc:GeometryOperand>' +
+        '<ogc:GeometryOperand>gml:Polygon</ogc:GeometryOperand>' +
+        '<ogc:GeometryOperand>gml:Point</ogc:GeometryOperand>' +
+        '<ogc:GeometryOperand>gml:LineString</ogc:GeometryOperand>' +
+      '</ogc:GeometryOperands>' +
+      '<ogc:SpatialOperators>' +
+        '<ogc:SpatialOperator name="BBOX"/>' +
+        '<ogc:SpatialOperator name="Contains"/>' +
+        '<ogc:SpatialOperator name="Intersects"/>' +
+        '<ogc:SpatialOperator name="Overlaps"/>' +
+      '</ogc:SpatialOperators>' +
+    '</ogc:Spatial_Capabilities>' +
+    '<ogc:Temporal_Capabilities>' +
+      '<ogc:TemporalOperands>' +
+        '<ogc:TemporalOperand>gml:TimeInstant</ogc:TemporalOperand>' +
+        '<ogc:TemporalOperand>gml:TimePeriod</ogc:TemporalOperand>' +
+      '</ogc:TemporalOperands>' +
+      '<ogc:TemporalOperators>' +
+        '<ogc:TemporalOperator name="TM_During"/>' +
+        '<ogc:TemporalOperator name="TM_Equals"/>' +
+        '<ogc:TemporalOperator name="TM_After"/>' +
+        '<ogc:TemporalOperator name="TM_Before"/>' +
+      '</ogc:TemporalOperators>' +
+    '</ogc:Temporal_Capabilities>' +
+    '<ogc:Scalar_Capabilities>' +
+      '<ogc:ComparisonOperators>' +
+        '<ogc:ComparisonOperator>Between</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>LessThan</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>LessThanEqualTo</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>GreaterThan</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>GreaterThanEqualTo</ogc:ComparisonOperator>' +
+        '<ogc:ComparisonOperator>Like</ogc:ComparisonOperator>' +
+      '</ogc:ComparisonOperators>' +
+    '</ogc:Scalar_Capabilities>' +
+    '<ogc:Id_Capabilities>' +
+      '<ogc:FID/>' +
+      '<ogc:EID/>' +
+    '</ogc:Id_Capabilities>' +
+  '</sos:Filter_Capabilities>' +
+  '<sos:Contents>' +
+    '<sos:ObservationOfferingList>' +
+      '<sos:ObservationOffering gml:id="ATMOSPHERIC_TEMPERATURE">' +
+        '<gml:name>Temperature of the atmosphere</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Temperature"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="RAIN_GAUGE">' +
+        '<gml:name>Rain</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-11-20T15:35:22+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Precipitation1Hour"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="WIND_DIRECTION">' +
+        '<gml:name>Direction of the wind</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::WindDirection"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="WIND_SPEED">' +
+        '<gml:name>Speed of the wind</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::WindSpeed"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="HUMIDITY">' +
+        '<gml:name>Humidity of the atmosphere</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-02-14T11:03:02+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::RelativeHumidity"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="LUMINANCE">' +
+        '<gml:name>Luminance</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-11-20T15:20:22+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Luminance"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+      '<sos:ObservationOffering gml:id="ATMOSPHERIC_PRESSURE">' +
+        '<gml:name>Pressure of the atmosphere</gml:name>' +
+        '<gml:boundedBy>' +
+          '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>' +
+            '<gml:upperCorner>51.9412 13.883498</gml:upperCorner>' +
+          '</gml:Envelope>' +
+        '</gml:boundedBy>' +
+        '<sos:time>' +
+          '<gml:TimePeriod xsi:type="gml:TimePeriodType">' +
+            '<gml:beginPosition>2008-12-20T02:29:27+01:00</gml:beginPosition>' +
+            '<gml:endPosition>2009-11-04T14:45:00+01:00</gml:endPosition>' +
+          '</gml:TimePeriod>' +
+        '</sos:time>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:observedProperty xlink:href="urn:x-ogc:def:property:OGC::BarometricPressure"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93"/>' +
+        '<sos:featureOfInterest xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>' +
+        '<sos:responseFormat>text/xml;subtype="om/1.0.0"</sos:responseFormat>' +
+        '<sos:responseFormat>application/zip</sos:responseFormat>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Measurement</sos:resultModel>' +
+        '<sos:resultModel xmlns:ns="http://www.opengis.net/om/1.0">ns:Observation</sos:resultModel>' +
+        '<sos:responseMode>inline</sos:responseMode>' +
+        '<sos:responseMode>resultTemplate</sos:responseMode>' +
+      '</sos:ObservationOffering>' +
+    '</sos:ObservationOfferingList>' +
+  '</sos:Contents>' +
+'</sos:Capabilities>'
+);
\ No newline at end of file

Copied: sandbox/ahocevar/playground/tests/Format/SOSGetFeatureOfInterest.html (from rev 10919, trunk/openlayers/tests/Format/SOSGetFeatureOfInterest.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/SOSGetFeatureOfInterest.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/SOSGetFeatureOfInterest.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,80 @@
+<html>
+<head>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_read_SOSGetFeatureOfInterest_single(t) {
+        t.plan(6);
+
+        var parser = new OpenLayers.Format.SOSGetFeatureOfInterest();
+        var text =
+            '<?xml version="1.0" encoding="UTF-8"?>' +
+            '<sa:SamplingPoint xmlns:sa="http://www.opengis.net/sampling/1.0" xmlns:gml="http://www.opengis.net/gml" gml:id="urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56">' +
+            '<gml:name>Roof of the IfGI</gml:name>' +
+            '<sa:position>' +
+            '<gml:Point>' +
+            '<gml:pos srsName="urn:ogc:def:crs:EPSG:4326">52.1524 5.3722</gml:pos>' +
+            '</gml:Point>' +
+            '</sa:position>' +
+            '</sa:SamplingPoint>';
+
+        var res = parser.read(text);
+        t.eq(res.length, 1, "One feature parsed from response");
+        t.eq(res[0].attributes.id, "urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56", "gml:id correctly parsed");
+        t.eq(res[0].attributes.name, "Roof of the IfGI", "gml:name correctly parsed");
+        t.eq(res[0].geometry instanceof OpenLayers.Geometry.Point, true, "Geometry is a point geometry");
+        t.eq(res[0].geometry.x, 5.3722, "Geometry x coordinate correctly parsed");
+        t.eq(res[0].geometry.y, 52.1524, "Geometry y coordinate correctly parsed");
+    }
+
+    function test_read_SOSGetFeatureOfInterest_multiple(t) {
+        t.plan(6);
+
+        var parser = new OpenLayers.Format.SOSGetFeatureOfInterest();
+        var text =
+            '<?xml version="1.0" encoding="UTF-8"?>' +
+            '<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml" xmlns:sa="http://www.opengis.net/sampling/1.0">' +
+            '<gml:featureMember>' +
+            '<sa:SamplingPoint gml:id="urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93">' +
+            '<gml:name>weather @ roof of the ifgi, MS, Germany</gml:name>' +
+            '<sa:position>' +
+            '<gml:Point>' +
+            '<gml:pos srsName="urn:ogc:def:crs:EPSG:4326">51.9412 7.6103</gml:pos>' +
+            '</gml:Point>' +
+            '</sa:position>' +
+            '</sa:SamplingPoint>' +
+            '</gml:featureMember>' +
+            '<gml:featureMember>' +
+            '<sa:SamplingPoint gml:id="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111">' +
+            '<gml:name>waether @ roof of the FH Kaernten, Villach, Austria</gml:name>' +
+            '<sa:position>' +
+            '<gml:Point>' +
+            '<gml:pos srsName="urn:ogc:def:crs:EPSG:4326">46.611644 13.883498</gml:pos>' +
+            '</gml:Point>' +
+            '</sa:position>' +
+            '</sa:SamplingPoint>' +
+            '</gml:featureMember>' +
+            '</gml:FeatureCollection>';
+
+        var res = parser.read(text);
+        t.eq(res.length, 2, "Two features parsed from response");
+        t.eq(res[0].attributes.id, "urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93", "gml:id correctly parsed");
+        t.eq(res[1].attributes.name, "waether @ roof of the FH Kaernten, Villach, Austria", "gml:name correctly parsed");
+        t.eq(res[1].geometry instanceof OpenLayers.Geometry.Point, true, "Geometry is a point geometry");
+        t.eq(res[1].geometry.x, 13.883498, "Geometry x coordinate correctly parsed");
+        t.eq(res[1].geometry.y, 46.611644, "Geometry y coordinate correctly parsed");
+    }
+
+    function test_write_SOSGetFeatureOfInterest(t) {
+        t.plan(1);
+        var expect = '<GetFeatureOfInterest xmlns="http://www.opengis.net/sos/1.0" version="1.0.0" service="SOS" xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><FeatureOfInterestId>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</FeatureOfInterestId><FeatureOfInterestId>urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111</FeatureOfInterestId></GetFeatureOfInterest>';
+        var format = new OpenLayers.Format.SOSGetFeatureOfInterest();
+        var output = format.writeNode("sos:GetFeatureOfInterest", {fois: ['urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93', 'urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111']});
+        t.xml_eq(output, expect, "Request XML is written out correctly");
+    }
+
+    </script>
+</head>
+<body>
+</body>
+</html>

Copied: sandbox/ahocevar/playground/tests/Format/SOSGetObservation.html (from rev 10919, trunk/openlayers/tests/Format/SOSGetObservation.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/SOSGetObservation.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/SOSGetObservation.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,183 @@
+<html>
+<head>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_read_SOSGetObservation(t) {
+        t.plan(13);
+
+        var parser = new OpenLayers.Format.SOSGetObservation();
+        var text =
+            '<?xml version="1.0" encoding="UTF-8"?>' +
+            '<om:ObservationCollection xmlns:om="http://www.opengis.net/om/1.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sa="http://www.opengis.net/sampling/1.0" gml:id="oc_0" xsi:schemaLocation="http://www.opengis.net/om/1.0 http://schemas.opengis.net/om/1.0.0/om.xsd http://www.opengis.net/sampling/1.0 http://schemas.opengis.net/sampling/1.0.0/sampling.xsd">' +
+            '<gml:boundedBy>' +
+            '<gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">' +
+            '<gml:lowerCorner>52.1524 5.3722</gml:lowerCorner>' +
+            '<gml:upperCorner>52.1524 5.3722</gml:upperCorner>' +
+            '</gml:Envelope>' +
+            '</gml:boundedBy>' +
+            '<om:member>' +
+            '<om:Measurement gml:id="o_51082">' +
+            '<om:samplingTime>' +
+            '<gml:TimeInstant xsi:type="gml:TimeInstantType">' +
+            '<gml:timePosition>2009-12-02T10:35:00.000+01:00</gml:timePosition>' +
+            '</gml:TimeInstant>' +
+            '</om:samplingTime>' +
+            '<om:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56"/>' +
+            '<om:observedProperty xlink:href="urn:x-ogc:def:property:OGC::Temperature"/>' +
+            '<om:featureOfInterest>' +
+            '<sa:SamplingPoint gml:id="urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56">' +
+            '<gml:name>Roof of the IfGI</gml:name>' +
+            '<sa:position>' +
+            '<gml:Point>' +
+            '<gml:pos srsName="urn:ogc:def:crs:EPSG:4326">52.1524 5.3722</gml:pos>' +
+            '</gml:Point>' +
+            '</sa:position>' +
+            '</sa:SamplingPoint>' +
+            '</om:featureOfInterest>' +
+            '<om:result uom="Cel">4.9</om:result>' +
+            '</om:Measurement>' +
+            '</om:member>' +
+            '</om:ObservationCollection>';
+
+        var res = parser.read(text);
+        t.eq(res.measurements.length, 1, "One measurement parsed");
+        t.eq(res.id, "oc_0", "Observation collection id correctly parsed");
+        var measurement = res.measurements[0];
+        t.eq(measurement.observedProperty, "urn:x-ogc:def:property:OGC::Temperature", "Observed property correctly parsed");
+        t.eq(measurement.procedure, "urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56", "Procedure correctly parsed");
+        t.eq(measurement.result.uom, "Cel", "Units of measurement correctly parsed");
+        t.eq(measurement.result.value, "4.9", "Value correctly parsed");
+        t.eq(measurement.samplingTime.timeInstant.timePosition, "2009-12-02T10:35:00.000+01:00", "Sampling time correctly parsed");
+
+        var response = [];
+        response.push('<?xml version="1.0" encoding="UTF-8"?>',
+'<om:ObservationCollection gml:id="oc_0" xsi:schemaLocation="http://www.opengis.net/om/1.0 http://schemas.opengis.net/om/1.0.0/om.xsd http://www.opengis.net/sampling/1.0 http://schemas.opengis.net/sampling/1.0.0/sampling.xsd" xmlns:om="http://www.opengis.net/om/1.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:swe="http://www.opengis.net/swe/1.0.1" xmlns:sa="http://www.opengis.net/sampling/1.0">',
+'  <gml:boundedBy>',
+'    <gml:Envelope srsName="urn:ogc:def:crs:EPSG:4326">',
+'      <gml:lowerCorner>46.611644 7.6103</gml:lowerCorner>',
+'      <gml:upperCorner>51.9412 13.883498</gml:upperCorner>',
+'    </gml:Envelope>',
+'  </gml:boundedBy>',
+'  <om:member>',
+'    <om:Observation gml:id="ot_583227">',
+'      <om:samplingTime>',
+'        <gml:TimePeriod xsi:type="gml:TimePeriodType">',
+'          <gml:beginPosition>2009-09-28T13:45:00.000+02:00</gml:beginPosition>',
+'          <gml:endPosition>2009-09-28T13:45:00.000+02:00</gml:endPosition>',
+'        </gml:TimePeriod>',
+'      </om:samplingTime>',
+'      <om:procedure xlink:href="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111"/>',
+'      <om:observedProperty>',
+'        <swe:CompositePhenomenon gml:id="cpid0" dimension="1">',
+'          <gml:name>resultComponents</gml:name>',
+'          <swe:component xlink:href="urn:ogc:data:time:iso8601"/>',
+'          <swe:component xlink:href="urn:ogc:def:property:OGC::Precipitation1Hour"/>',
+'        </swe:CompositePhenomenon>',
+'      </om:observedProperty>',
+'      <om:featureOfInterest>',
+'        <gml:FeatureCollection>',
+'          <gml:featureMember>',
+'            <sa:SamplingPoint gml:id="urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111" xsi:schemaLocation=" http://www.opengis.net/sampling/1.0 http://schemas.opengis.net/sampling/1.0.0/sampling.xsd">',
+'              <gml:name>waether @ roof of the FH Kaernten, Villach, Austria</gml:name>',
+'              <sa:sampledFeature xlink:href="urn:ogc:def:nil:OGC:unknown"/>',
+'              <sa:position>',
+'                <gml:Point>',
+'                  <gml:pos srsName="urn:ogc:def:crs:EPSG:4326">46.611644 13.883498</gml:pos>',
+'                </gml:Point>',
+'              </sa:position>',
+'            </sa:SamplingPoint>',
+'          </gml:featureMember>',
+'        </gml:FeatureCollection>',
+'      </om:featureOfInterest>',
+'      <om:result>',
+'        <swe:DataArray>',
+'          <swe:elementCount>',
+'            <swe:Count>',
+'              <swe:value>1</swe:value>',
+'            </swe:Count>',
+'          </swe:elementCount>',
+'          <swe:elementType name="Components">',
+'            <swe:DataRecord>',
+'              <swe:field name="Time">',
+'                <swe:Time definition="urn:ogc:data:time:iso8601"/>',
+'              </swe:field>',
+'              <swe:field name="feature">',
+'                <swe:Text definition="urn:ogc:data:feature"/>',
+'              </swe:field>',
+'              <swe:field name="urn:ogc:def:property:OGC::Precipitation1Hour">',
+'                <swe:Quantity definition="urn:ogc:def:property:OGC::Precipitation1Hour">',
+'                  <swe:uom code="mm"/>',
+'                </swe:Quantity>',
+'              </swe:field>',
+'            </swe:DataRecord>',
+'          </swe:elementType>',
+'          <swe:encoding>',
+'            <swe:TextBlock decimalSeparator="." tokenSeparator="," blockSeparator=";"/>',
+'          </swe:encoding>',
+'          <swe:values>2009-09-28T13:45:00.000+02:00,urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111,0.0;</swe:values>',
+'        </swe:DataArray>',
+'      </om:result>',
+'    </om:Observation>',
+'  </om:member>',
+'</om:ObservationCollection>');
+        text = response.join("");
+        var res = parser.read(text);
+        t.eq(res.observations.length, 1, "1 observation parsed");
+        var observation = res.observations[0];
+        t.eq(observation.procedure, "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "procedure parsed correctly");
+        t.eq(observation.fois.length, 1, "One foi parsed for the observation");
+        var foi = observation.fois[0];
+        var feature = foi.features[0];
+        t.eq(feature.attributes.id, "urn:ogc:object:feature:OSIRIS-HWS:efeb807b-bd24-4128-a920-f6729bcdd111", "Foi id correctly parsed");
+        t.eq(feature.attributes.name, "waether @ roof of the FH Kaernten, Villach, Austria", "Foi name correctly parsed");
+        t.ok(feature.geometry instanceof OpenLayers.Geometry.Point, "Geometry correctly parsed");
+    }
+
+    function test_write_SOSGetObservation(t) {
+        t.plan(2);
+        var expect = '<GetObservation xmlns="http://www.opengis.net/sos/1.0" version="1.0.0" service="SOS" xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><offering>TEMPERATURE</offering><eventTime><ogc:TM_Equals xmlns:ogc="http://www.opengis.net/ogc"><ogc:PropertyName>urn:ogc:data:time:iso8601</ogc:PropertyName><gml:TimeInstant xmlns:gml="http://www.opengis.net/gml"><gml:timePosition>latest</gml:timePosition></gml:TimeInstant></ogc:TM_Equals></eventTime><procedure>urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56</procedure><observedProperty>urn:x-ogc:def:property:OGC::Temperature</observedProperty><responseFormat>text/xml;subtype="om/1.0.0"</responseFormat><resultModel>Measurement</resultModel><responseMode>inline</responseMode></GetObservation>';
+        var format = new OpenLayers.Format.SOSGetObservation();
+        var output = format.write({eventTime: 'latest', resultModel: 'Measurement', responseMode: 'inline',
+            procedures: ['urn:ogc:object:feature:OSIRIS-HWS:4fc335bc-06d7-4d5e-a72a-1ac73b9f3b56'], responseFormat: 'text/xml;subtype="om/1.0.0"',
+            offering: 'TEMPERATURE', observedProperties: ['urn:x-ogc:def:property:OGC::Temperature']});
+        t.xml_eq(output, expect, "Request XML is written out correctly");
+
+        var expected = [];
+
+        expected.push('<?xml version="1.0" encoding="UTF-8"?>',
+'<GetObservation xmlns="http://www.opengis.net/sos/1.0"',
+'  xmlns:gml="http://www.opengis.net/gml"',
+'  xmlns:om="http://www.opengis.net/om/1.0"',
+'  xmlns:ogc="http://www.opengis.net/ogc"',
+'  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
+'  xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd"',
+'  service="SOS" version="1.0.0">',
+'  <offering>RAIN_GAUGE</offering>',
+'  <eventTime>',
+'    <ogc:TM_Equals>',
+'      <ogc:PropertyName>urn:ogc:data:time:iso8601</ogc:PropertyName>',
+'      <gml:TimeInstant>',
+'        <gml:timePosition>latest</gml:timePosition>',
+'      </gml:TimeInstant>',
+'    </ogc:TM_Equals>',
+'  </eventTime>',
+'  <observedProperty>urn:ogc:def:property:OGC::Precipitation1Hour</observedProperty>',
+'  <featureOfInterest>',
+'    <ObjectID>urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93</ObjectID>',
+'  </featureOfInterest>',
+'  <responseFormat>text/xml;subtype="om/1.0.0"</responseFormat>',
+'</GetObservation>');
+        expect = expected.join("");
+        var output = format.write({eventTime: 'latest', offering: 'RAIN_GAUGE',
+            observedProperties: ['urn:ogc:def:property:OGC::Precipitation1Hour'],
+            responseFormat: 'text/xml;subtype="om/1.0.0"',
+            foi: {objectId: 'urn:ogc:object:feature:OSIRIS-HWS:3d3b239f-7696-4864-9d07-15447eae2b93'}});
+        t.xml_eq(output, expect, "Request XML is written out correctly");
+    }
+
+    </script>
+</head>
+<body>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Format/WFSCapabilities/v1.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WFSCapabilities/v1.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WFSCapabilities/v1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,7 +4,7 @@
     <script type="text/javascript">
     
     function test_read(t) {
-        t.plan(11);
+        t.plan(30);
        
         var parser = new OpenLayers.Format.WFSCapabilities();
 
@@ -15,7 +15,8 @@
         t.eq(ft.length, 14, "number of feature types correct");
         t.eq(ft[0]["abstract"], "Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs", "abstract of first feature type correct");
         t.eq(ft[0]["title"], "Manhattan (NY) landmarks", "title of first feature type correct");
-        t.eq(ft[0]["name"], "tiger:poly_landmarks", "name of first feature type correct");
+        t.eq(ft[0]["name"], "poly_landmarks", "name of first feature type correct");
+        t.eq(ft[0]["featureNS"], "http://www.census.gov", "ns of first feature type correct");
 
         // GeoServer, v1.0.0
         text = '<?xml version="1.0" encoding="UTF-8"?><WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:it.geosolutions="http://www.geo-solutions.it" xmlns:cite="http://www.opengeospatial.net/cite" xmlns:tiger="http://www.census.gov" xmlns:sde="http://geoserver.sf.net" xmlns:topp="http://www.openplans.org/topp" xmlns:sf="http://www.openplans.org/spearfish" xmlns:nurc="http://www.nurc.nato.int" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:80/geoserver/schemas/wfs/1.0.0/WFS-capabilities.xsd"><Service><Name>WFS</Name><Title>GeoServer Web Feature Service</Title><Abstract>This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.</Abstract><Keywords>WFS, WMS, GEOSERVER</Keywords><OnlineResource>http://localhost:80/geoserver/wfs</OnlineResource><Fees>NONE</Fees><AccessConstraints>NONE</Acce
 ssConstraints></Service><Capability><Request><GetCapabilities><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=GetCapabilities"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></GetCapabilities><DescribeFeatureType><SchemaDescriptionLanguage><XMLSCHEMA/></SchemaDescriptionLanguage><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=DescribeFeatureType"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></DescribeFeatureType><GetFeature><ResultFormat><GML2/><SHAPE-ZIP/><GEOJSON/><csv/><GML3/></ResultFormat><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=GetFeature"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></GetFeature><Transaction><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=T
 ransaction"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></Transaction><LockFeature><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=LockFeature"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></LockFeature><GetFeatureWithLock><ResultFormat><GML2/></ResultFormat><DCPType><HTTP><Get onlineResource="http://localhost:80/geoserver/wfs?request=GetFeatureWithLock"/></HTTP></DCPType><DCPType><HTTP><Post onlineResource="http://localhost:80/geoserver/wfs?"/></HTTP></DCPType></GetFeatureWithLock></Request></Capability><FeatureTypeList><Operations><Query/><Insert/><Update/><Delete/><Lock/></Operations><FeatureType><Name>tiger:poly_landmarks</Name><Title>Manhattan (NY) landmarks</Title><Abstract>Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs</Abstract><Keywords>DS_poly_landmarks, poly_landmarks, landmarks,
  manhattan</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="-74.047185" miny="40.679648" maxx="-73.90782" maxy="40.882078"/></FeatureType><FeatureType><Name>tiger:poi</Name><Title>Manhattan (NY) points of interest</Title><Abstract>Points of interest in New York, New York (on Manhattan). One of the attributes contains the name of a file with a picture of the point of interest.</Abstract><Keywords>poi, DS_poi, points_of_interest, Manhattan</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="-74.0118315772888" miny="40.70754683896324" maxx="-74.00857344353275" maxy="40.711945649065406"/></FeatureType><FeatureType><Name>tiger:tiger_roads</Name><Title>Manhattan (NY) roads</Title><Abstract>Highly simplified road layout of Manhattan in New York..</Abstract><Keywords>DS_tiger_roads, tiger_roads, roads</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="-74.02722" miny="40.684221" maxx="-73.907005" maxy="40.878178"/></FeatureType><FeatureType><Name>sf:archsites</Name><
 Title>Spearfish archeological sites</Title><Abstract>Sample data from GRASS, archeological sites location, Spearfish, South Dakota, USA</Abstract><Keywords>archsites, sfArchsites, spearfish, archeology</Keywords><SRS>EPSG:26713</SRS><LatLongBoundingBox minx="-103.8725637911543" miny="44.37740330855979" maxx="-103.63794182141925" maxy="44.48804280772808"/></FeatureType><FeatureType><Name>sf:bugsites</Name><Title>Spearfish bug locations</Title><Abstract>Sample data from GRASS, bug sites location, Spearfish, South Dakota, USA</Abstract><Keywords>sfBugsites, bugsites, insects, spearfish, tiger_beetles</Keywords><SRS>EPSG:26713</SRS><LatLongBoundingBox minx="-103.86796131703647" miny="44.373938816704396" maxx="-103.63773523234195" maxy="44.43418821380063"/></FeatureType><FeatureType><Name>sf:restricted</Name><Title>Spearfish restricted areas</Title><Abstract>Sample data from GRASS, restricted areas, Spearfish, South Dakota, USA</Abstract><Keywords>restricted, sfRestricted, spearf
 ish, areas</Keywords><SRS>EPSG:26713</SRS><LatLongBoundingBox minx="-103.85057172920756" miny="44.39436387625042" maxx="-103.74741494853805" maxy="44.48215752041131"/></FeatureType><FeatureType><Name>sf:roads</Name><Title>Spearfish roads</Title><Abstract>Sample data from GRASS, road layout, Spearfish, South Dakota, USA</Abstract><Keywords>sfRoads, roads, spearfish</Keywords><SRS>EPSG:26713</SRS><LatLongBoundingBox minx="-103.87741691493184" miny="44.37087275281798" maxx="-103.62231404880659" maxy="44.50015918338962"/></FeatureType><FeatureType><Name>sf:streams</Name><Title>Spearfish streams</Title><Abstract>Sample data from GRASS, streams, Spearfish, South Dakota, USA</Abstract><Keywords>sfStreams, streams, spearfish</Keywords><SRS>EPSG:26713</SRS><LatLongBoundingBox minx="-103.87789019829768" miny="44.372335260095554" maxx="-103.62287788915457" maxy="44.502218486214815"/></FeatureType><FeatureType><Name>topp:tasmania_cities</Name><Title>Tasmania cities</Title><Abstract>Citi
 es in Tasmania (actually, just the capital)</Abstract><Keywords>cities, Tasmania</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="145.19754" miny="-43.423512" maxx="148.27298000000002" maxy="-40.852802"/></FeatureType><FeatureType><Name>topp:tasmania_roads</Name><Title>Tasmania roads</Title><Abstract>Main Tasmania roads</Abstract><Keywords>Roads, Tasmania</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="145.19754" miny="-43.423512" maxx="148.27298000000002" maxy="-40.852802"/></FeatureType><FeatureType><Name>topp:tasmania_state_boundaries</Name><Title>Tasmania state boundaries</Title><Abstract>Tasmania state boundaries</Abstract><Keywords>tasmania_state_boundaries, Tasmania, boundaries</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/></FeatureType><FeatureType><Name>topp:tasmania_water_bodies</Name><Title>Tasmania water bodies</Title><Abstract>Tasmania water bodies</Abstra
 ct><Keywords>Lakes, Bodies, Australia, Water, Tasmania</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="145.97161899999998" miny="-43.031944" maxx="147.219696" maxy="-41.775558"/></FeatureType><FeatureType><Name>topp:states</Name><Title>USA Population</Title><Abstract>This is some census data on the states.</Abstract><Keywords>census, united, boundaries, state, states</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="-124.731422" miny="24.955967" maxx="-66.969849" maxy="49.371735"/></FeatureType><FeatureType><Name>tiger:giant_polygon</Name><Title>World rectangle</Title><Abstract>A simple rectangular polygon covering most of the world, it\'s only used for the purpose of providing a background (WMS bgcolor could be used instead)</Abstract><Keywords>DS_giant_polygon, giant_polygon</Keywords><SRS>EPSG:4326</SRS><LatLongBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/></FeatureType></FeatureTypeList><ogc:Filter_Capabilities><ogc:Spatial_Capabilities><
 ogc:Spatial_Operators><ogc:Disjoint/><ogc:Equals/><ogc:DWithin/><ogc:Beyond/><ogc:Intersect/><ogc:Touches/><ogc:Crosses/><ogc:Within/><ogc:Contains/><ogc:Overlaps/><ogc:BBOX/></ogc:Spatial_Operators></ogc:Spatial_Capabilities><ogc:Scalar_Capabilities><ogc:Logical_Operators/><ogc:Comparison_Operators><ogc:Simple_Comparisons/><ogc:Between/><ogc:Like/><ogc:NullCheck/></ogc:Comparison_Operators><ogc:Arithmetic_Operators><ogc:Simple_Arithmetic/><ogc:Functions><ogc:Function_Names><ogc:Function_Name nArgs="1">abs</ogc:Function_Name><ogc:Function_Name nArgs="1">abs_2</ogc:Function_Name><ogc:Function_Name nArgs="1">abs_3</ogc:Function_Name><ogc:Function_Name nArgs="1">abs_4</ogc:Function_Name><ogc:Function_Name nArgs="1">acos</ogc:Function_Name><ogc:Function_Name nArgs="1">Area</ogc:Function_Name><ogc:Function_Name nArgs="1">asin</ogc:Function_Name><ogc:Function_Name nArgs="1">atan</ogc:Function_Name><ogc:Function_Name nArgs="2">atan2</ogc:Function_Name><ogc:Function_Name nArgs="3">b
 etween</ogc:Function_Name><ogc:Function_Name nArgs="1">boundary</ogc:Function_Name><ogc:Function_Name nArgs="1">boundaryDimension</ogc:Function_Name><ogc:Function_Name nArgs="2">buffer</ogc:Function_Name><ogc:Function_Name nArgs="3">bufferWithSegments</ogc:Function_Name><ogc:Function_Name nArgs="1">ceil</ogc:Function_Name><ogc:Function_Name nArgs="1">centroid</ogc:Function_Name><ogc:Function_Name nArgs="2">classify</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Average</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Bounds</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Count</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Max</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Median</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Min</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Sum</ogc:Function_Name><ogc:Function_Name nArgs="1">Collection_Unique</ogc:Function_Name><ogc:Function_Name nArgs="2">Con
 catenate</ogc:Function_Name><ogc:Function_Name nArgs="2">contains</ogc:Function_Name><ogc:Function_Name nArgs="1">convexHull</ogc:Function_Name><ogc:Function_Name nArgs="1">cos</ogc:Function_Name><ogc:Function_Name nArgs="2">crosses</ogc:Function_Name><ogc:Function_Name nArgs="2">dateFormat</ogc:Function_Name><ogc:Function_Name nArgs="2">dateParse</ogc:Function_Name><ogc:Function_Name nArgs="2">difference</ogc:Function_Name><ogc:Function_Name nArgs="1">dimension</ogc:Function_Name><ogc:Function_Name nArgs="2">disjoint</ogc:Function_Name><ogc:Function_Name nArgs="2">distance</ogc:Function_Name><ogc:Function_Name nArgs="1">double2bool</ogc:Function_Name><ogc:Function_Name nArgs="1">endPoint</ogc:Function_Name><ogc:Function_Name nArgs="1">envelope</ogc:Function_Name><ogc:Function_Name nArgs="2">EqualInterval</ogc:Function_Name><ogc:Function_Name nArgs="2">equalsExact</ogc:Function_Name><ogc:Function_Name nArgs="3">equalsExactTolerance</ogc:Function_Name><ogc:Function_Name nArgs
 ="2">equalTo</ogc:Function_Name><ogc:Function_Name nArgs="1">exp</ogc:Function_Name><ogc:Function_Name nArgs="1">exteriorRing</ogc:Function_Name><ogc:Function_Name nArgs="1">floor</ogc:Function_Name><ogc:Function_Name nArgs="1">geometryType</ogc:Function_Name><ogc:Function_Name nArgs="1">geomFromWKT</ogc:Function_Name><ogc:Function_Name nArgs="1">geomLength</ogc:Function_Name><ogc:Function_Name nArgs="2">getGeometryN</ogc:Function_Name><ogc:Function_Name nArgs="1">getX</ogc:Function_Name><ogc:Function_Name nArgs="1">getY</ogc:Function_Name><ogc:Function_Name nArgs="1">getZ</ogc:Function_Name><ogc:Function_Name nArgs="2">greaterEqualThan</ogc:Function_Name><ogc:Function_Name nArgs="2">greaterThan</ogc:Function_Name><ogc:Function_Name nArgs="0">id</ogc:Function_Name><ogc:Function_Name nArgs="2">IEEEremainder</ogc:Function_Name><ogc:Function_Name nArgs="3">if_then_else</ogc:Function_Name><ogc:Function_Name nArgs="11">in10</ogc:Function_Name><ogc:Function_Name nArgs="3">in2</ogc
 :Function_Name><ogc:Function_Name nArgs="4">in3</ogc:Function_Name><ogc:Function_Name nArgs="5">in4</ogc:Function_Name><ogc:Function_Name nArgs="6">in5</ogc:Function_Name><ogc:Function_Name nArgs="7">in6</ogc:Function_Name><ogc:Function_Name nArgs="8">in7</ogc:Function_Name><ogc:Function_Name nArgs="9">in8</ogc:Function_Name><ogc:Function_Name nArgs="10">in9</ogc:Function_Name><ogc:Function_Name nArgs="1">int2bbool</ogc:Function_Name><ogc:Function_Name nArgs="1">int2ddouble</ogc:Function_Name><ogc:Function_Name nArgs="1">interiorPoint</ogc:Function_Name><ogc:Function_Name nArgs="2">interiorRingN</ogc:Function_Name><ogc:Function_Name nArgs="2">intersection</ogc:Function_Name><ogc:Function_Name nArgs="2">intersects</ogc:Function_Name><ogc:Function_Name nArgs="1">isClosed</ogc:Function_Name><ogc:Function_Name nArgs="1">isEmpty</ogc:Function_Name><ogc:Function_Name nArgs="2">isLike</ogc:Function_Name><ogc:Function_Name nArgs="1">isNull</ogc:Function_Name><ogc:Function_Name nArgs
 ="1">isRing</ogc:Function_Name><ogc:Function_Name nArgs="1">isSimple</ogc:Function_Name><ogc:Function_Name nArgs="1">isValid</ogc:Function_Name><ogc:Function_Name nArgs="3">isWithinDistance</ogc:Function_Name><ogc:Function_Name nArgs="1">length</ogc:Function_Name><ogc:Function_Name nArgs="2">lessEqualThan</ogc:Function_Name><ogc:Function_Name nArgs="2">lessThan</ogc:Function_Name><ogc:Function_Name nArgs="1">log</ogc:Function_Name><ogc:Function_Name nArgs="2">max</ogc:Function_Name><ogc:Function_Name nArgs="2">max_2</ogc:Function_Name><ogc:Function_Name nArgs="2">max_3</ogc:Function_Name><ogc:Function_Name nArgs="2">max_4</ogc:Function_Name><ogc:Function_Name nArgs="2">min</ogc:Function_Name><ogc:Function_Name nArgs="2">min_2</ogc:Function_Name><ogc:Function_Name nArgs="2">min_3</ogc:Function_Name><ogc:Function_Name nArgs="2">min_4</ogc:Function_Name><ogc:Function_Name nArgs="1">not</ogc:Function_Name><ogc:Function_Name nArgs="2">notEqualTo</ogc:Function_Name><ogc:Function_N
 ame nArgs="1">numGeometries</ogc:Function_Name><ogc:Function_Name nArgs="1">numInteriorRing</ogc:Function_Name><ogc:Function_Name nArgs="1">numPoints</ogc:Function_Name><ogc:Function_Name nArgs="2">overlaps</ogc:Function_Name><ogc:Function_Name nArgs="1">parseBoolean</ogc:Function_Name><ogc:Function_Name nArgs="1">parseDouble</ogc:Function_Name><ogc:Function_Name nArgs="1">parseInt</ogc:Function_Name><ogc:Function_Name nArgs="0">pi</ogc:Function_Name><ogc:Function_Name nArgs="2">pointN</ogc:Function_Name><ogc:Function_Name nArgs="2">pow</ogc:Function_Name><ogc:Function_Name nArgs="1">PropertyExists</ogc:Function_Name><ogc:Function_Name nArgs="2">Quantile</ogc:Function_Name><ogc:Function_Name nArgs="0">random</ogc:Function_Name><ogc:Function_Name nArgs="2">relate</ogc:Function_Name><ogc:Function_Name nArgs="3">relatePattern</ogc:Function_Name><ogc:Function_Name nArgs="1">rint</ogc:Function_Name><ogc:Function_Name nArgs="1">round</ogc:Function_Name><ogc:Function_Name nArgs="1"
 >round_2</ogc:Function_Name><ogc:Function_Name nArgs="1">roundDouble</ogc:Function_Name><ogc:Function_Name nArgs="1">sin</ogc:Function_Name><ogc:Function_Name nArgs="1">sqrt</ogc:Function_Name><ogc:Function_Name nArgs="2">StandardDeviation</ogc:Function_Name><ogc:Function_Name nArgs="1">startPoint</ogc:Function_Name><ogc:Function_Name nArgs="2">strConcat</ogc:Function_Name><ogc:Function_Name nArgs="2">strEndsWith</ogc:Function_Name><ogc:Function_Name nArgs="2">strEqualsIgnoreCase</ogc:Function_Name><ogc:Function_Name nArgs="2">strIndexOf</ogc:Function_Name><ogc:Function_Name nArgs="2">strLastIndexOf</ogc:Function_Name><ogc:Function_Name nArgs="1">strLength</ogc:Function_Name><ogc:Function_Name nArgs="2">strMatches</ogc:Function_Name><ogc:Function_Name nArgs="4">strReplace</ogc:Function_Name><ogc:Function_Name nArgs="2">strStartsWith</ogc:Function_Name><ogc:Function_Name nArgs="3">strSubstring</ogc:Function_Name><ogc:Function_Name nArgs="2">strSubstringStart</ogc:Function_Nam
 e><ogc:Function_Name nArgs="1">strToLowerCase</ogc:Function_Name><ogc:Function_Name nArgs="1">strToUpperCase</ogc:Function_Name><ogc:Function_Name nArgs="1">strTrim</ogc:Function_Name><ogc:Function_Name nArgs="2">symDifference</ogc:Function_Name><ogc:Function_Name nArgs="1">tan</ogc:Function_Name><ogc:Function_Name nArgs="1">toDegrees</ogc:Function_Name><ogc:Function_Name nArgs="1">toRadians</ogc:Function_Name><ogc:Function_Name nArgs="2">touches</ogc:Function_Name><ogc:Function_Name nArgs="1">toWKT</ogc:Function_Name><ogc:Function_Name nArgs="2">union</ogc:Function_Name><ogc:Function_Name nArgs="2">UniqueInterval</ogc:Function_Name><ogc:Function_Name nArgs="2">within</ogc:Function_Name></ogc:Function_Names></ogc:Functions></ogc:Arithmetic_Operators></ogc:Scalar_Capabilities></ogc:Filter_Capabilities></WFS_Capabilities>';
@@ -24,8 +25,25 @@
         t.eq(ft.length, 14, "number of feature types correct");
         t.eq(ft[0]["abstract"], "Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs", "abstract of first feature type correct");
         t.eq(ft[0]["title"], "Manhattan (NY) landmarks", "title of first feature type correct");
-        t.eq(ft[0]["name"], "tiger:poly_landmarks", "name of first feature type correct");
+        t.eq(ft[0]["name"], "poly_landmarks", "name of first feature type correct");
+        t.eq(ft[0]["featureNS"], "http://www.census.gov", "ns of first feature type correct");
+
+        var service = res.service;
+        t.eq(service.name, 'WFS', "service name correct");
+        t.eq(service.title, 'GeoServer Web Feature Service', "service title correct");
+        t.eq(service.abstract, 'This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.', "service title correct");
+        t.eq(service.keywords[0], 'WFS', "service keyword [0] correct");
+        t.eq(service.keywords[2], 'GEOSERVER', "service keyword [2] correct");
+        t.eq(service.onlineResource, 'http://localhost:80/geoserver/wfs', "service onlineresource correct");
+        t.ok(typeof service.fees == 'undefined', "service fees correct");
+        t.ok(typeof service.accessConstraints == 'undefined', "service accessconstraints correct");
         
+        t.eq(res.capability.request.getfeature.href.post, "http://localhost:80/geoserver/wfs?", "getfeature request post href correct");
+        t.eq(res.capability.request.getfeature.href.get, "http://localhost:80/geoserver/wfs?request=GetFeature", "getfeature request get href correct");
+        
+        t.eq(res.capability.request.getfeature.formats[0], "GML2", "getfeature response format [0] correct");
+        t.eq(res.capability.request.getfeature.formats[4], "GML3", "getfeature response format [4] correct");
+        
         // UMN Mapserer, v1.0.0
         text =
             '<?xml version="1.0" encoding="ISO-8859-1" ?>' +
@@ -119,6 +137,13 @@
         t.eq(ft.length, 2, "number of feature types correct");
         t.eq(ft[0]["title"], "Parks", "title of first feature type correct");
         t.eq(ft[0]["name"], "park", "name of first feature type correct");
+        
+        var service = res.service;
+        t.eq(service.name, 'MapServer WFS', "service name correct");
+        t.eq(service.title, 'GMap WMS Demo Server', "service title correct");
+        t.eq(service.onlineResource, 'http://127.0.0.1/cgi-bin/mapserv_40?map=/msroot/apache/htdocs/gmap/htdocs/gmap75_wfs.map&service=WFS&', "service onlineresource correct");
+        t.eq(res.capability.request.getfeature.href.get, "http://127.0.0.1/cgi-bin/mapserv_40?map=/msroot/apache/htdocs/gmap/htdocs/gmap75_wfs.map&service=WFS&", "getfeature request get href correct");
+        t.eq(res.capability.request.getfeature.formats[0], "GML2", "getfeature response format [0] correct");        
     }
 
     </script> 

Modified: sandbox/ahocevar/playground/tests/Format/WFST/v1.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WFST/v1.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WFST/v1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -12,53 +12,109 @@
             featureType: "states"
         });
         var features = format.read(data);
-        
+
         t.eq(features.length, 1, "number of features read from FeatureCollection is correct");
     }
-    
+
     function test_write(t) {
-        
+
         var format = new OpenLayers.Format.WFST({
             featureNS: "http://www.openplans.org/topp",
             featureType: "states",
             featurePrefix: "topp",
             geometryName: "the_geom"
         });
-        
+
         var feature = new OpenLayers.Feature.Vector(
             new OpenLayers.Geometry.Point(1,2),
-            {foo: "bar"});
-            
+            {foo: "bar"}
+        );
+
         var insertFeature = feature.clone();
+        // null value does not show up in insert
+        insertFeature.attributes.nul = null;
         insertFeature.state = OpenLayers.State.INSERT;
         var updateFeature = feature.clone();
+        // undefined value means don't create a Property element
+        updateFeature.attributes.unwritten = undefined;
+        // null value gets Property element with no Value
+        updateFeature.attributes.nul = null;
         updateFeature.fid = "fid.42";
         updateFeature.state = OpenLayers.State.UPDATE;
         var deleteFeature = feature.clone();
         deleteFeature.state = OpenLayers.State.DELETE;
         deleteFeature.fid = "fid.37";
-        
+
         t.plan(5);
         var snippets = {
-            "GetFeature": {maxFeatures: 1},
+            "GetFeature": {maxFeatures: 1, outputFormat: 'json'},
             "Transaction": null,
             "Insert": insertFeature,
             "Update": updateFeature,
             "Delete": deleteFeature
         }
-        
+
         var arg;
         for(var snippet in snippets) {
             arg = snippets[snippet]
             var expected = readXML(snippet);
             var got = format.writers["wfs"][snippet].apply(format, [arg]);
             t.xml_eq(got, expected, snippet + " request created correctly");
-        }       
+        }
     }
-    
+
+    function test_write_no_geometry(t) {
+        var format = new OpenLayers.Format.WFST({
+            featureNS: "http://www.openplans.org/topp",
+            featureType: "states",
+            featurePrefix: "topp",
+            geometryName: null
+        });
+
+        var feature = new OpenLayers.Feature.Vector(null, {foo: "bar"});
+        feature.state = OpenLayers.State.UPDATE;
+        feature.fid = "fid.36";
+
+        t.plan(1);
+        var snippets = {
+            "UpdateNoGeometry": feature
+        }
+
+        var arg;
+        for(var snippet in snippets) {
+            arg = snippets[snippet]
+            var expected = readXML(snippet);
+            var got = format.writers["wfs"]["Update"].apply(format, [arg]);
+            t.xml_eq(got, expected, snippet + " request without geometry created correctly");
+        }
+    }
+
+    function test_write_multiple(t) {
+
+        var format = new OpenLayers.Format.WFST({
+            featureNS: "http://www.openplans.org/topp",
+            featureType: ["states", "cities"],
+            featurePrefix: "topp",
+            geometryName: "the_geom"
+        });
+
+        t.plan(1);
+        var snippets = {
+            "GetFeatureMultiple": {}
+        }
+        
+        var arg;
+        for(var snippet in snippets) {
+            arg = snippets[snippet]
+            var expected = readXML(snippet);
+            var got = format.writers["wfs"]["GetFeature"].apply(format, [arg]);
+            t.xml_eq(got, expected, snippet + " request created correctly with multiple typenames");
+        }
+    }
+
     function readXML(id) {
         var xml = document.getElementById(id).firstChild.nodeValue;
-        return new OpenLayers.Format.XML().read(xml).documentElement;        
+        return new OpenLayers.Format.XML().read(xml).documentElement;
     }
 
   </script>
@@ -111,10 +167,16 @@
 --></div>
 
 <div id="GetFeature"><!--
-<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0" maxFeatures="1" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0" outputFormat="json" maxFeatures="1" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <wfs:Query typeName="topp:states" xmlns:topp="http://www.openplans.org/topp"/>
 </wfs:GetFeature>
 --></div>
+<div id="GetFeatureMultiple"><!--
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <wfs:Query typeName="topp:states" xmlns:topp="http://www.openplans.org/topp"/>
+    <wfs:Query typeName="topp:cities" xmlns:topp="http://www.openplans.org/topp"/>
+</wfs:GetFeature>
+--></div>
 <div id="Transaction"><!--
 <wfs:Transaction xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0"/>
 --></div>
@@ -144,6 +206,9 @@
         <wfs:Name>foo</wfs:Name>
         <wfs:Value>bar</wfs:Value>
     </wfs:Property>
+    <wfs:Property>
+        <wfs:Name>nul</wfs:Name>
+    </wfs:Property>
     <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
         <ogc:FeatureId fid="fid.42"/>
     </ogc:Filter>
@@ -156,5 +221,16 @@
     </ogc:Filter>
 </wfs:Delete>
 --></div>
+<div id="UpdateNoGeometry"><!--
+<wfs:Update xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
+    <wfs:Property>
+        <wfs:Name>foo</wfs:Name>
+        <wfs:Value>bar</wfs:Value>
+    </wfs:Property>
+    <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
+        <ogc:FeatureId fid="fid.36"/>
+    </ogc:Filter>
+</wfs:Update>
+--></div>
 </body>
 </html>

Modified: sandbox/ahocevar/playground/tests/Format/WFST/v1_0_0.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WFST/v1_0_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WFST/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -42,6 +42,13 @@
                 })
             }
         }, {
+            id: "query1",
+            writer: "wfs:Query",
+            arg: {
+                srsNameInQuery: true,
+                srsName: "EPSG:900913"
+            }
+        }, {
             id: "getfeature0",
             writer: "wfs:GetFeature",
             arg: {
@@ -94,6 +101,10 @@
     </ogc:Filter>
 </wfs:Query>
 --></div>
+<div id="query1"><!--
+<wfs:Query xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" srsName="EPSG:900913" xmlns:topp="http://www.openplans.org/topp">
+</wfs:Query>
+--></div>
 <div id="getfeature0"><!--
 <wfs:GetFeature service="WFS" version="1.0.0" xmlns:topp="http://www.openplans.org/topp"
                 xmlns:wfs="http://www.opengis.net/wfs"

Modified: sandbox/ahocevar/playground/tests/Format/WFST/v1_1_0.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WFST/v1_1_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WFST/v1_1_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -22,13 +22,25 @@
         t.eq(result.insertIds[0], "none", "InsertIds read correctly");
         t.eq(result.success, true, "Success read correctly");
     }
-    
+
+    function test_read_hits(t) {
+        t.plan(1);
+        var data = readXML("NumberOfFeatures");
+        var format = new OpenLayers.Format.WFST.v1_1_0({
+            featureNS: "http://mapserver.gis.umn.edu/mapserver",
+            featureType: "AAA64"
+        });
+        var result = format.read(data, {output: "object"});
+        t.eq(result.numberOfFeatures, 625, "numberOfFeatures of FeatureCollection correctly read");
+    }
+
     function test_write(t) {
 
         var format = new OpenLayers.Format.WFST.v1_1_0({
             featureNS: "http://www.openplans.org/topp",
             featureType: "states",
             featurePrefix: "topp",
+            srsName: "urn:ogc:def:crs:EPSG::4326",
             geometryName: "the_geom"
         });
 
@@ -45,6 +57,7 @@
             id: "getfeature0",
             writer: "wfs:GetFeature",
             arg: {
+                resultType: "hits",
                 propertyNames: ["STATE_NAME", "STATE_FIPS", "STATE_ABBR"]
             }
         }];
@@ -70,6 +83,17 @@
 </head>
 <body>
 <div id="map" style="width:512px; height:256px"> </div>
+<div id="NumberOfFeatures"><!--
+<?xml version='1.0' encoding="ISO-8859-1" ?>
+<wfs:FeatureCollection
+   xmlns:rws="http://mapserver.gis.umn.edu/mapserver"
+   xmlns:gml="http://www.opengis.net/gml"
+   xmlns:wfs="http://www.opengis.net/wfs"
+   xmlns:ogc="http://www.opengis.net/ogc"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver http://intranet.rijkswaterstaat.nl/services/geoservices/nwb_wegen?SERVICE=WFS&amp;VERSION=1.1.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=feature:AAA64&amp;OUTPUTFORMAT=text/xml; subtype=gml/3.1.1  http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" numberOfFeatures="625">
+</wfs:FeatureCollection>
+--></div>
 <div id="TransactionResponse"><!--
 <wfs:TransactionResponse version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:tiger="http://www.census.gov" xmlns:wfs="http://www.opengis.net/wfs" xmlns:topp="http://www.openplans.org/topp" xmlns:sf="http://www.openplans.org/spearfish" xmlns:ows="http://www.opengis.net/ows" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink">
     <wfs:TransactionSummary>
@@ -86,11 +110,11 @@
 </wfs:TransactionResponse>
 --></div>
 <div id="query0"><!--
-<wfs:Query xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
+<wfs:Query xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" srsName="urn:ogc:def:crs:EPSG::4326" xmlns:topp="http://www.openplans.org/topp">
     <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
         <ogc:BBOX>
             <ogc:PropertyName>the_geom</ogc:PropertyName>
-            <gml:Envelope xmlns:gml="http://www.opengis.net/gml">
+            <gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="urn:ogc:def:crs:EPSG::4326">
                 <gml:lowerCorner>1 2</gml:lowerCorner>
                 <gml:upperCorner>3 4</gml:upperCorner>
             </gml:Envelope>
@@ -99,12 +123,12 @@
 </wfs:Query>
 --></div>
 <div id="getfeature0"><!--
-<wfs:GetFeature service="WFS" version="1.1.0" xmlns:topp="http://www.openplans.org/topp"
+<wfs:GetFeature service="WFS" version="1.1.0" resultType="hits" xmlns:topp="http://www.openplans.org/topp"
                 xmlns:wfs="http://www.opengis.net/wfs"
                 xmlns:ogc="http://www.opengis.net/ogc"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
-    <wfs:Query xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
+    <wfs:Query xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" srsName="urn:ogc:def:crs:EPSG::4326" xmlns:topp="http://www.openplans.org/topp">
         <wfs:PropertyName>STATE_NAME</wfs:PropertyName>
         <wfs:PropertyName>STATE_FIPS</wfs:PropertyName>
         <wfs:PropertyName>STATE_ABBR</wfs:PropertyName>

Modified: sandbox/ahocevar/playground/tests/Format/WKT.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WKT.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WKT.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -108,9 +108,9 @@
  
         // test a multipoint 
         t.eq(format.write(multipoint), 
-             "MULTIPOINT(" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
-                             points[1].geometry.x + " " + points[1].geometry.y + "," + 
-                             points[2].geometry.x + " " + points[2].geometry.y + ")", 
+             "MULTIPOINT((" + points[0].geometry.x + " " + points[0].geometry.y + "),(" + 
+                              points[1].geometry.x + " " + points[1].geometry.y + "),(" + 
+                              points[2].geometry.x + " " + points[2].geometry.y + "))", 
              "format correctly writes MultiPoint WKT"); 
  
         // test a linestring 

Modified: sandbox/ahocevar/playground/tests/Format/WMC/v1.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMC/v1.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMC/v1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -6,9 +6,10 @@
     function test_write_wmc_StyleList(t) {
         t.plan(3);
         
-        var layer, got, expected;
+        var layer, layerContext, got, expected;
         
-        var parser = new OpenLayers.Format.WMC.v1();
+        var format = new OpenLayers.Format.WMC();
+        var parser = format.getParser("1");
         var name = "test";
         var url = "http://foo";
 
@@ -16,7 +17,8 @@
         layer = new OpenLayers.Layer.WMS(name, url, {
             styles: "mystyle"
         });
-        got = parser.write_wmc_StyleList(layer);
+        layerContext = format.layerToContext(layer);
+        got = parser.write_wmc_StyleList(layerContext);
         expected = 
             "<StyleList xmlns='http://www.opengis.net/context'>" +
                 "<Style current='1'>" +
@@ -31,7 +33,8 @@
         layer = new OpenLayers.Layer.WMS(name, url, {
             sld: "http://linked.sld"
         });
-        got = parser.write_wmc_StyleList(layer);
+        layerContext = format.layerToContext(layer);
+        got = parser.write_wmc_StyleList(layerContext);
         expected = 
             "<StyleList xmlns='http://www.opengis.net/context'>" +
                 "<Style current='1'>" +
@@ -39,6 +42,7 @@
                         "<OnlineResource xmlns:xlink='http://www.w3.org/1999/xlink' "+
                                         "xlink:type='simple' " +
                                         "xlink:href='http://linked.sld' />" +
+                        "<Name></Name><Title>Default</Title>" +
                     "</SLD>" + 
                 "</Style>" +
             "</StyleList>";
@@ -78,7 +82,8 @@
                 "</sld:StyledLayerDescriptor>"
         });
         
-        got = parser.write_wmc_StyleList(layer);
+        layerContext = format.layerToContext(layer);
+        got = parser.write_wmc_StyleList(layerContext);
         expected =
             "<StyleList xmlns='http://www.opengis.net/context'>" +
                 "<Style current='1'>" +
@@ -110,6 +115,7 @@
                                 "</sld:UserStyle>" +
                             "</sld:NamedLayer>" +
                         "</sld:StyledLayerDescriptor>" +
+                        "<Name></Name><Title>Default</Title>" +
                     "</SLD>" +
                 "</Style>" + 
             "</StyleList>";
@@ -122,8 +128,9 @@
         t.plan(3);
         
         var xml = new OpenLayers.Format.XML();
-        var parser = new OpenLayers.Format.WMC.v1();
-        var node, text, layerInfo;
+        var format = new OpenLayers.Format.WMC();
+        var parser = format.getParser("1");
+        var node, text, layerContext, layer;
 
         // test named style
         text = 
@@ -133,12 +140,12 @@
                 "</Style>" +
             "</StyleList>";
         node = xml.read(text).documentElement;
-        layerInfo = {
-            params: {},
+        layerContext = {
             styles: []
         };
-        parser.read_wmc_StyleList(layerInfo, node);
-        t.eq(layerInfo.params.styles, "mystyle", "named style correctly read");
+        parser.read_wmc_StyleList(layerContext, node);
+        layer = format.getLayerFromContext(layerContext);
+        t.eq(layer.params.STYLES, "mystyle", "named style correctly read");
         
         // test linked style
         text = 
@@ -152,12 +159,12 @@
                 "</Style>" +
             "</StyleList>";
         node = xml.read(text).documentElement;
-        layerInfo = {
-            params: {},
+        layerContext = {
             styles: []
         };
-        parser.read_wmc_StyleList(layerInfo, node);
-        t.eq(layerInfo.params.sld, "http://linked.sld", "linked style correctly read");        
+        parser.read_wmc_StyleList(layerContext, node);
+        layer = format.getLayerFromContext(layerContext);
+        t.eq(layer.params.SLD, "http://linked.sld", "linked style correctly read");        
         
         // test inline style
         // any valid xml under the StyledLayerDescriptor node should make the
@@ -176,11 +183,11 @@
                 "</Style>" +
             "</StyleList>";
         node = xml.read(text).documentElement;
-        layerInfo = {
-            params: {},
+        layerContext = {
             styles: []
         };
-        parser.read_wmc_StyleList(layerInfo, node);        
+        parser.read_wmc_StyleList(layerContext, node);        
+        layer = format.getLayerFromContext(layerContext);
         var expected = 
             "<sld:StyledLayerDescriptor version='1.0.0' " +
                 "xmlns:sld='http://www.opengis.net/sld' " +
@@ -188,7 +195,7 @@
                 "xsi:schemaLocation='http://www.opengis.net/sld http://schemas.opengeospatial.net/sld/1.0.0/StyledLayerDescriptor.xsd'>" +
                 "<foo xmlns='http://www.opengis.net/context'>bar<more/></foo>" + 
             "</sld:StyledLayerDescriptor>";
-        t.xml_eq(layerInfo.params.sld_body, expected, "inline style correctly read");
+        t.xml_eq(layer.params.SLD_BODY, expected, "inline style correctly read");
 
     }
     

Modified: sandbox/ahocevar/playground/tests/Format/WMC/v1_1_0.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMC/v1_1_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMC/v1_1_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,30 +1,32 @@
-<html> 
-<head> 
-    <script src="../../../lib/OpenLayers.js"></script> 
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
     <script type="text/javascript">
-    
+
     function test_write_wmc_Layer(t) {
-        if (OpenLayers.Util.getBrowserName() == "safari") {
+        if (OpenLayers.BROWSER_NAME == "safari") {
             t.plan(0);
             t.debug_print("Safari has wierd behavior with getElementsByTagNameNS: the result is that we can't run these tests there. Patches welcome.");
             return;
         }
-        t.plan(10);
-        
+        t.plan(12);
+
         // direct construction of a parser for a unit test
-        var wmc = new OpenLayers.Format.WMC.v1_1_0();
-        var sldNS = wmc.namespaces["sld"];
-        
+        var format = new OpenLayers.Format.WMC();
+        var parser = format.getParser("1_1_0");
+        var sldNS = parser.namespaces["sld"];
+
         // test that Min/MaxScaleDenominator is not written out when no
         // resolution related options are set
         var layer = new OpenLayers.Layer.WMS(
             "test", "http://foo", {},
             {maxExtent: new OpenLayers.Bounds(1, 2, 3, 4)}
         );
-        var node = wmc.write_wmc_Layer(layer);
-        var minList = wmc.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
+        var layerContext = format.layerToContext(layer);
+        var node = parser.write_wmc_Layer(layerContext);
+        var minList = parser.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
         t.eq(minList.length, 0, "(none) node not written with MinScaleDenominator");
-        var maxList = wmc.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
+        var maxList = parser.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
         t.eq(maxList.length, 0, "(none) node not written with MaxScaleDenominator");
 
         // test that Min/MaxScaleDenominator is written out for explicit
@@ -35,40 +37,50 @@
         );
         layer.minScale = Math.random();
         layer.maxScale = Math.random();
-        sldNS = wmc.namespaces["sld"];
-        node = wmc.write_wmc_Layer(layer);
-        minList = wmc.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
+        sldNS = parser.namespaces["sld"];
+        layerContext = format.layerToContext(layer);
+        node = parser.write_wmc_Layer(layerContext);
+        minList = parser.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
         t.eq(minList.length, 1, "(resolutions) node written with MinScaleDenominator");
-        t.eq(layer.maxScale.toPrecision(10), wmc.getChildValue(minList[0]),
+        t.eq(layer.maxScale.toPrecision(16), parser.getChildValue(minList[0]),
              "(resolutions) node written with correct MinScaleDenominator value");
-        maxList = wmc.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
+        maxList = parser.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
         t.eq(maxList.length, 1, "(resolutions) node written with MaxScaleDenominator");
-        t.eq(layer.minScale.toPrecision(10), wmc.getChildValue(maxList[0]),
+        t.eq(layer.minScale.toPrecision(16), parser.getChildValue(maxList[0]),
              "(resolutions) node written with correct MaxScaleDenominator value");
-        
+
         layer = new OpenLayers.Layer.WMS(
             "test", "http://foo", {},
             {scales: [4, 2, 1], maxExtent: new OpenLayers.Bounds(1, 2, 3, 4)}
         );
         layer.minScale = Math.random();
         layer.maxScale = Math.random();
-        node = wmc.write_wmc_Layer(layer);
-        minList = wmc.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
+        layerContext = format.layerToContext(layer);
+        node = parser.write_wmc_Layer(layerContext);
+        minList = parser.getElementsByTagNameNS(node, sldNS, "MinScaleDenominator");
         var f = new OpenLayers.Format.XML();
         t.eq(minList.length, 1, "(scales) node written with MinScaleDenominator");
-        t.eq(layer.maxScale.toPrecision(10), wmc.getChildValue(minList[0]),
+        t.eq(layer.maxScale.toPrecision(16), parser.getChildValue(minList[0]),
              "(scales) node written with correct MinScaleDenominator value");
-        maxList = wmc.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
+        maxList = parser.getElementsByTagNameNS(node, sldNS, "MaxScaleDenominator");
         t.eq(maxList.length, 1, "(scales) node written with MaxScaleDenominator");
-        t.eq(layer.minScale.toPrecision(10), wmc.getChildValue(maxList[0]),
+        t.eq(layer.minScale.toPrecision(16), parser.getChildValue(maxList[0]),
              "(scales) node written with correct MaxScaleDenominator value");
-        
+
+        layer.metadataURL = 'http://foo';
+        layerContext = format.layerToContext(layer);
+        node = parser.write_wmc_Layer(layerContext);
+        t.eq(node.childNodes[3].localName || node.childNodes[3].nodeName.split(":").pop(),
+            'MetadataURL', "MinScaleDenominator is written after MetadataURL, so third node should be MetadataURL");
+        t.eq(node.childNodes[4].localName || node.childNodes[4].nodeName.split(":").pop(),
+            'MinScaleDenominator', "MinScaleDenominator is written after MetadataURL, so fourth node should be MinScaleDenominator");
+
     }
-    
 
-    </script> 
-</head> 
+
+    </script>
+</head>
 <body>
     <div id="map" style="width: 512px; height: 256px;"></div>
-</body> 
-</html> 
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Format/WMC.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMC.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMC.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -3,11 +3,11 @@
     <script src="../../lib/OpenLayers.js"></script> 
     <script type="text/javascript">
 
-    var v1_0_0 = '<ViewContext xmlns="http://www.opengis.net/context" version="1.0.0" id="OpenLayers_Context_233" xsi:schemaLocation="http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><Window width="512" height="256"/><BoundingBox minx="-109.9709708" miny="27.01451459" maxx="-80.02902918" maxy="41.98548541" SRS="EPSG:4326"/><Title/><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/></Extension></General><LayerList><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://t1.hypercube.telascience.org/cgi-bin/landsat7"/></Server><Name>landsat7</Name><Title>NASA Global Mosaic</Title><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><N
 ame/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="1"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://labs.metacarta.com/wms/vmap0"/></Server><Name>basic</Name><Title>OpenLayers WMS</Title><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default
 </Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://lioapp.lrc.gov.on.ca/cubeserv/cubeserv.pl"/></Server><Name>na_road:CCRS</Name><Title>Transportation Network</Title><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title
 >Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-166.5320000" miny="4.050460000" maxx="-0.2068180000" maxy="70.28700000"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.6</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">false</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://columbo.nrlssc.navy.mil/ogcwms/servlet/WMSServlet/AccuWeather_M
 aps.wms"/></Server><Name>3:1</Name><Title>Radar 3:1</Title><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-131.0294952" miny="14.56289673" maxx="-61.02950287" maxy="54.56289673"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.8</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">true</ol:singleTile></Extension></Layer></LayerList></ViewContext>';
-    var v1_1_0 = '<ViewContext xmlns="http://www.opengis.net/context" version="1.1.0" id="OpenLayers_Context_232" xsi:schemaLocation="http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><Window width="512" height="256"/><BoundingBox minx="-109.9709708" miny="27.01451459" maxx="-80.02902918" maxy="41.98548541" SRS="EPSG:4326"/><Title/><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/></Extension></General><LayerList><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://t1.hypercube.telascience.org/cgi-bin/landsat7"/></Server><Name>landsat7</Name><Title>NASA Global Mosaic</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:MinScaleDenomin
 ator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="1"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://
 labs.metacarta.com/wms/vmap0"/></Server><Name>basic</Name><Title>OpenLayers WMS</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extensi
 on></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://lioapp.lrc.gov.on.ca/cubeserv/cubeserv.pl"/></Server><Name>na_road:CCRS</Name><Title>Transportation Network</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6200000.000</sld:MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">32000000.00</sld:MaxScaleDenominator><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-166.5320000" miny="4.050460000" maxx="-0.2068180000" maxy="70.28700000"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/co
 ntext">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.6</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">false</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://columbo.nrlssc.navy.mil/ogcwms/servlet/WMSServlet/AccuWeather_Maps.wms"/></Server><Name>3:1</Name><Title>Radar 3:1</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title>
 </Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-131.0294952" miny="14.56289673" maxx="-61.02950287" maxy="54.56289673"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.8</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">true</ol:singleTile></Extension></Layer></LayerList></ViewContext>';
+    var v1_0_0 = '<ViewContext xmlns="http://www.opengis.net/context" version="1.0.0" id="OpenLayers_Context_233" xsi:schemaLocation="http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><Window width="512" height="256"/><BoundingBox minx="-109.9709708" miny="27.01451459" maxx="-80.02902918" maxy="41.98548541" SRS="EPSG:4326"/><Title/><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/></Extension></General><LayerList><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://t1.hypercube.telascience.org/cgi-bin/landsat7"/></Server><Name>landsat7</Name><Title>NASA Global Mosaic</Title><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><N
 ame/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile><ol:tileSize xmlns:ol="http://openlayers.org/context" width="512" height="1024"/></Extension></Layer><Layer queryable="1" hidden="1"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://labs.metacarta.com/wms/vmap0"/></Server><Name>basic</Name><Title>OpenLayers WMS</Title><FormatList><Format current="1">im
 age/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://lioapp.lrc.gov.on.ca/cubeserv/cubeserv.pl"/></Server><Name>na_road:CCRS</Name><Title>Transportation Network</Title><FormatList><Format curre
 nt="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-166.5320000" miny="4.050460000" maxx="-0.2068180000" maxy="70.28700000"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.6</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">false</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" x
 link:href="http://columbo.nrlssc.navy.mil/ogcwms/servlet/WMSServlet/AccuWeather_Maps.wms"/></Server><Name>3:1</Name><Title>Radar 3:1</Title><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-131.0294952" miny="14.56289673" maxx="-61.02950287" maxy="54.56289673"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.8</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">false</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">true</ol:singleTile></Extension
 ></Layer></LayerList></ViewContext>';
+    var v1_1_0 = '<ViewContext xmlns="http://www.opengis.net/context" version="1.1.0" id="OpenLayers_Context_232" xsi:schemaLocation="http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><General><Window width="512" height="256"/><BoundingBox minx="-109.9709708" miny="27.01451459" maxx="-80.02902918" maxy="41.98548541" SRS="EPSG:4326"/><Title/><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/></Extension></General><LayerList><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://t1.hypercube.telascience.org/cgi-bin/landsat7"/></Server><Name>landsat7</Name><Title>NASA Global Mosaic</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:MinScaleDenomin
 ator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:tileSize xmlns:ol="http://openlayers.org/context" width="512" height="1024"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="1"><Server service="OGC:WMS" version="1.1.1"><OnlineResource x
 link:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://labs.metacarta.com/wms/vmap0"/></Server><Name>basic</Name><Title>OpenLayers WMS</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/jpeg</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-130.0000000" miny="14.00000000" maxx="-60.00000000" maxy="55.00000000"/><ol:tileSize xmlns:ol="http://openlayers.org/context" width="512" height="1024"/><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">true</ol:isBaseLayer><ol:displayInLayerSwitch
 er xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://lioapp.lrc.gov.on.ca/cubeserv/cubeserv.pl"/></Server><Name>na_road:CCRS</Name><Title>Transportation Network</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6200000.000</sld:MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">32000000.00</sld:MaxScaleDenominator><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-166.5320000" miny="4.050460000" maxx="-0.2068180000" maxy="70.28700000"/><ol:tileSize xmlns:ol="http://openlayer
 s.org/context" width="512" height="1024"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.6</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">false</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">false</ol:singleTile></Extension></Layer><Layer queryable="1" hidden="0"><Server service="OGC:WMS" version="1.1.1"><OnlineResource xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://columbo.nrlssc.navy.mil/ogcwms/servlet/WMSServlet/AccuWeather_Maps.wms"/></Server><Name>3:1</Name><Title>Radar 3:1</Title><sld:MinScaleDenominator xmlns:sld="http://www.opengis.net/sld">6299645.760</sld:
 MinScaleDenominator><sld:MaxScaleDenominator xmlns:sld="http://www.opengis.net/sld">31498228.80</sld:MaxScaleDenominator><FormatList><Format current="1">image/png</Format></FormatList><StyleList><Style current="1"><Name/><Title>Default</Title></Style></StyleList><Extension><ol:maxExtent xmlns:ol="http://openlayers.org/context" minx="-131.0294952" miny="14.56289673" maxx="-61.02950287" maxy="54.56289673"/><ol:transparent xmlns:ol="http://openlayers.org/context">TRUE</ol:transparent><ol:numZoomLevels xmlns:ol="http://openlayers.org/context">4</ol:numZoomLevels><ol:units xmlns:ol="http://openlayers.org/context">degrees</ol:units><ol:isBaseLayer xmlns:ol="http://openlayers.org/context">false</ol:isBaseLayer><ol:opacity xmlns:ol="http://openlayers.org/context">0.8</ol:opacity><ol:displayInLayerSwitcher xmlns:ol="http://openlayers.org/context">true</ol:displayInLayerSwitcher><ol:singleTile xmlns:ol="http://openlayers.org/context">true</ol:singleTile></Extension></Layer></LayerList
 ></ViewContext>';
 
     function test_Format_WMC_read(t) {
-        t.plan(33);
+        t.plan(36);
 
         var format = new OpenLayers.Format.WMC();        
         var map, layer;
@@ -32,6 +32,10 @@
              "(v1.0.0) layer numZoomLevels correctly set");
         t.eq(layer.isBaseLayer, true,
              "(v1.0.0) layer isBaseLayer correctly set for base layer");
+        t.eq(layer.tileSize.w, 512, 
+             "(v1.0.0) layer tileSize width correctly set");
+        t.eq(layer.tileSize.h, 1024, 
+             "(v1.0.0) layer tileSize height correctly set");
         // check out layer not in switcher
         layer = map.layers[2];
         t.eq(layer.displayInLayerSwitcher, false, 
@@ -86,6 +90,12 @@
         t.eq(layer.opacity, 0.8, 
              "(v1.1.0) layer opacity correctly set");
         map.destroy();
+
+        // test mapOptions
+        var map = format.read(v1_1_0, {map: {foo: 'bar', div: 'map'}});
+        t.eq(map.foo, "bar",
+            "mapOptions correctly passed to the created map object");
+        map.destroy();
         
     }
     
@@ -120,7 +130,7 @@
          */
 
         // test v1.1.0
-        if(OpenLayers.Util.getBrowserName()== "opera") {
+        if(OpenLayers.BROWSER_NAME== "opera") {
             t.plan(0);
             t.debug_print("WMC writing works but is not tested in Opera");
         } else {

Modified: sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_1_1.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_1_1.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_1_1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,13 +1,14 @@
 <html> 
 <head> 
     <script src="../../../lib/OpenLayers.js"></script>
-    <script src="v1_1_1.js"></script>
     <script type="text/javascript">
     
     function test_read(t) {
         
-        t.plan(13);
-        
+        t.plan(15);
+
+        var xml = document.getElementById("gssample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
         var format = new OpenLayers.Format.WMSCapabilities();
         var obj = format.read(doc);
         
@@ -27,6 +28,7 @@
         
         var layer = capability.layers[2];
         t.eq(layer.name, "tiger:tiger_roads", "[2] correct layer name");
+        t.eq(layer.prefix, "tiger", "[2] correct layer prefix");
         t.eq(layer.title, "Manhattan (NY) roads", "[2] correct layer title");
         t.eq(
             layer["abstract"],
@@ -45,13 +47,5094 @@
             "http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&FORMAT=image/png&WIDTH=20&HEIGHT=20&LAYER=tiger:tiger_roads",
             "[2] correct legend url"
         );
+        t.eq(
+            layer.styles[0].legend.format, "image/png",
+            "[2] correct legend format"
+        );
         t.eq(layer.queryable, true, "[2] correct queryable attribute");
         
+
     }
+
+    function test_layers(t) {
+
+        t.plan(22);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        var layers = {};
+        for (var i=0, len=capability.layers.length; i<len; i++) {
+            if ("name" in capability.layers[i]) {
+                layers[ capability.layers[i].name ] = capability.layers[i];
+            }
+        }
+
+        var rootlayer = capability.layers[ capability.layers.length - 1];
+
+        t.eq(rootlayer.srs, 
+             {"EPSG:4326": true},
+             "SRS parsed correctly for root layer");
+        t.eq(layers["ROADS_RIVERS"].srs,
+             {"EPSG:4326": true, "EPSG:26986": true},
+             "Inheritance of SRS handled correctly when adding SRSes");
+        t.eq(layers["Temperature"].srs,
+             {"EPSG:4326": true},
+             "Inheritance of SRS handled correctly when redeclaring an inherited SRS");
+
+        var bbox = layers["ROADS_RIVERS"].bbox["EPSG:26986"];
+        t.eq(bbox.bbox,
+             [189000, 834000, 285000, 962000],
+             "Correct bbox from BoundingBox");
+        t.eq(bbox.res, {x: 1, y: 1}, "Correct resolution");
+
+        bbox = layers["ROADS_1M"].bbox["EPSG:26986"];
+        t.eq(bbox.bbox,
+             [189000, 834000, 285000, 962000],
+             "Correctly inherited bbox");
+        t.eq(bbox.res, {x: 1, y: 1}, "Correctly inherited resolution");
+
+
+        var identifiers = layers["ROADS_RIVERS"].identifiers;
+        var authorities = layers["ROADS_RIVERS"].authorityURLs;
+
+        t.ok(identifiers, "got identifiers from layer ROADS_RIVERS");
+        t.ok("DIF_ID" in identifiers,
+             "authority attribute from Identifiers parsed correctly");
+        t.eq(identifiers["DIF_ID"],
+             "123456",
+             "Identifier value parsed correctly");
+        t.ok("DIF_ID" in authorities,
+             "AuthorityURLs parsed and inherited correctly");
+        t.eq(authorities["DIF_ID"],
+             "http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html",
+             "OnlineResource in AuthorityURLs parsed correctly");
+
+        var featurelist = layers["ROADS_RIVERS"].featureListURL;
+        t.ok(featurelist, "layer has FeatureListURL");
+        t.eq(featurelist.format,
+             "application/vnd.ogc.se_xml",
+             "FeatureListURL format parsed correctly");
+        t.eq(featurelist.href,
+             "http://www.university.edu/data/roads_rivers.gml",
+             "FeatureListURL OnlineResource parsed correctly");
+
+        t.eq(layers["Pressure"].queryable,
+             true,
+             "queryable property inherited correctly");
+        t.eq(layers["ozone_image"].queryable,
+             false,
+             "queryable property has correct default value");
+        t.eq(layers["population"].cascaded,
+             1,
+             "cascaded property parsed correctly");
+        t.eq(layers["ozone_image"].fixedWidth,
+             512,
+             "fixedWidth property correctly parsed");
+        t.eq(layers["ozone_image"].fixedHeight,
+             256,
+             "fixedHeight property correctly parsed");
+        t.eq(layers["ozone_image"].opaque,
+             true,
+             "opaque property parsed correctly");
+        t.eq(layers["ozone_image"].noSubsets,
+             true,
+             "noSubsets property parsed correctly");
+
+
+    }
+
+    function test_dimensions(t) {
+
+        t.plan(8);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        var layers = {};
+        for (var i=0, len=capability.layers.length; i<len; i++) {
+            if ("name" in capability.layers[i]) {
+                layers[ capability.layers[i].name ] = capability.layers[i];
+            }
+        }
+
+        var time = layers["Clouds"].dimensions.time;
+        t.eq(time["default"], "2000-08-22", "Default time value parsed correctly");
+        t.eq(time.values.length, 1, "Currect number of time extent values/periods");
+        t.eq(time.values[0], "1999-01-01/2000-08-22/P1D", "Time extent values parsed correctly");
+
+        var elevation = layers["Pressure"].dimensions.elevation;
+        t.eq(elevation.units, "EPSG:5030", "Dimension units parsed correctly");
+        t.eq(elevation["default"], "0", "Default elevation value parsed correctly");
+        t.eq(elevation.nearestVal, true, "NearestValue parsed correctly");
+        t.eq(elevation.multipleVal, false, "Absense of MultipleValues handled correctly");
+        t.eq(elevation.values,
+             ["0","1000","3000","5000","10000"],
+             "Parsing of comma-separated values done correctly");
+
+
+    }
+
+    function test_contactinfo(t) {
+        t.plan(15);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var service = obj.service;
+
+        var contactinfo = service.contactInformation;
+        t.ok(contactinfo, "object contains contactInformation property");
+
+        var personPrimary = contactinfo.personPrimary;
+        t.ok(personPrimary, "object contains personPrimary property");
+
+        t.eq(personPrimary.person, "Jeff deLaBeaujardiere", "ContactPerson parsed correctly");
+        t.eq(personPrimary.organization, "NASA", "ContactOrganization parsed correctly");
+
+        t.eq(contactinfo.position,
+             "Computer Scientist",
+             "ContactPosition parsed correctly");
+
+
+        var addr = contactinfo.contactAddress;
+        t.ok(addr, "object contains contactAddress property");
+
+        t.eq(addr.type, "postal", "AddressType parsed correctly");
+        t.eq(addr.address,
+             "NASA Goddard Space Flight Center, Code 933",
+             "Address parsed correctly");
+        t.eq(addr.city, "Greenbelt", "City parsed correctly");
+        t.eq(addr.stateOrProvince, "MD", "StateOrProvince parsed correctly");
+        t.eq(addr.postcode, "20771", "PostCode parsed correctly");
+        t.eq(addr.country, "USA", "Country parsed correctly");
+
+        t.eq(contactinfo.phone,
+             "+1 301 286-1569",
+             "ContactVoiceTelephone parsed correctly");
+        t.eq(contactinfo.fax,
+             "+1 301 286-1777",
+             "ContactFacsimileTelephone parsed correctly");
+        t.eq(contactinfo.email,
+             "delabeau at iniki.gsfc.nasa.gov",
+             "ContactElectronicMailAddress parsed correctly");
+    }
     
+    function test_feesAndConstraints(t) {
+        t.plan(2);
+
+        var xml = document.getElementById("gssample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var service = obj.service;
+
+        t.ok(! ("fees" in service), "Fees=none handled correctly");
+        t.ok(! ("accessConstraints" in service), "AccessConstraints=none handled correctly");
+    }
+
+    function test_requests(t) {
+        t.plan(13);
+
+        var xml = document.getElementById("gssample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var request = obj.capability.request;
+
+        t.ok(request, "request property exists");
+        t.ok("getmap" in request, "got GetMap request");
+
+        t.ok("getfeatureinfo" in request, "got GetFeatureInfo request");
+        t.eq(request.getfeatureinfo.formats,
+             ["text/plain", "text/html", "application/vnd.ogc.gml"],
+             "GetFeatureInfo formats correctly parsed");
+
+        t.ok("describelayer" in request, "got DescribeLayer request");
+
+        t.ok("getlegendgraphic" in request, "got GetLegendGraphic request");
+
+        var exception = obj.capability.exception;
+        t.ok(exception, "exception property exists");
+        t.eq(exception.formats,
+             ["application/vnd.ogc.se_xml"],
+             "Exception Format parsed");
+
+        var userSymbols = obj.capability.userSymbols;
+        t.ok(userSymbols, "userSymbols property exists");
+        t.eq(userSymbols.supportSLD, true, "supportSLD parsed");
+        t.eq(userSymbols.userLayer,  true, "userLayer parsed");
+        t.eq(userSymbols.userStyle,  true, "userStyle parsed");
+        t.eq(userSymbols.remoteWFS,  true, "remoteWFS parsed");
+
+    }
+    function test_ogc(t) {
+        t.plan(14)
+
+        /*
+         * Set up
+         */
+        
+        // needed for the minScale/maxScale test, see below
+        var dpi = OpenLayers.DOTS_PER_INCH;
+        OpenLayers.DOTS_PER_INCH = 90.71;
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        /*
+         * Test
+         */
+        
+        var attribution = capability.layers[2].attribution;
+        t.eq(attribution.title, "State College University", "attribution title parsed correctly.");
+        t.eq(attribution.href, "http://www.university.edu/", "attribution href parsed correctly.")
+        t.eq(attribution.logo.href, "http://www.university.edu/icons/logo.gif", "attribution logo url parsed correctly.");
+        t.eq(attribution.logo.format, "image/gif", "attribution logo format parsed correctly.");
+        t.eq(attribution.logo.width, "100", "attribution logo width parsed correctly.");
+        t.eq(attribution.logo.height, "100", "attribution logo height parsed correctly.");
+        
+        var keywords = capability.layers[0].keywords;
+        t.eq(keywords.length, 3, "layer has 3 keywords.");
+        t.eq(keywords[0], "road", "1st keyword parsed correctly.");
+        
+        var metadataURLs = capability.layers[0].metadataURLs;
+        t.eq(metadataURLs.length, 2, "layer has 2 metadata urls.");
+        t.eq(metadataURLs[0].type, "FGDC", "type parsed correctly.");
+        t.eq(metadataURLs[0].format, "text/plain", "format parsed correctly.");
+        t.eq(metadataURLs[0].href, "http://www.university.edu/metadata/roads.txt", "href parsed correctly.");
+
+        /*
+        Test minScale and maxScale
+
+        For Mapserver
+
+        <ScaleHint min="0.395998292216226" max="98.9995730540565" />
+
+        corresponds to (RESOLUTION keyword in MAP file has value of 90.71):
+
+        MAXSCALE 250000
+        MINSCALE 1000
+
+        */
+        t.eq(capability.layers[0].minScale, 250000, "layer.minScale is correct");
+        t.eq(capability.layers[0].maxScale, 1000, "layer.maxScale is correct");
+
+        /*
+         * Tear down
+         */
+
+        OpenLayers.DOTS_PER_INCH = dpi;
+    }
     
     </script> 
 </head> 
 <body>
+
+<!--
+OGC example below taken from
+http://schemas.opengis.net/wms/1.1.1/capabilities_1_1_1.xml
+Copyright © 1994-2008 Open Geospatial Consortium, Inc. All Rights Reserved.
+http://www.opengeospatial.org/ogc/document
+Changes:
+* fixed DTD URL
+* removed comments
+-->
+<div id="ogcsample"><!--
+<?xml version='1.0' encoding="UTF-8" standalone="no" ?>
+<!DOCTYPE WMT_MS_Capabilities SYSTEM
+ "http://schemas.opengis.net/wms/1.1.1/capabilities_1_1_1.dtd"
+ [
+ <!ELEMENT VendorSpecificCapabilities EMPTY>
+ ]>
+
+<WMT_MS_Capabilities version="1.1.1" updateSequence="0">
+<Service>
+
+  <Name>OGC:WMS</Name>
+  <Title>Acme Corp. Map Server</Title>
+  <Abstract>WMT Map Server maintained by Acme Corporation.  Contact: webmaster at wmt.acme.com.  High-quality maps showing roadrunner nests and possible ambush locations.</Abstract>
+  <KeywordList>
+
+    <Keyword>bird</Keyword>
+    <Keyword>roadrunner</Keyword>
+    <Keyword>ambush</Keyword>
+  </KeywordList>
+  <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+   xlink:href="http://hostname/" />
+
+  <ContactInformation>
+    <ContactPersonPrimary>
+      <ContactPerson>Jeff deLaBeaujardiere</ContactPerson>
+      <ContactOrganization>NASA</ContactOrganization>
+    </ContactPersonPrimary>
+    <ContactPosition>Computer Scientist</ContactPosition>
+    <ContactAddress>
+
+      <AddressType>postal</AddressType>
+      <Address>NASA Goddard Space Flight Center, Code 933</Address>
+      <City>Greenbelt</City>
+      <StateOrProvince>MD</StateOrProvince>
+      <PostCode>20771</PostCode>
+      <Country>USA</Country>
+
+    </ContactAddress>
+    <ContactVoiceTelephone>+1 301 286-1569</ContactVoiceTelephone>
+    <ContactFacsimileTelephone>+1 301 286-1777</ContactFacsimileTelephone>
+    <ContactElectronicMailAddress>delabeau at iniki.gsfc.nasa.gov</ContactElectronicMailAddress>
+  </ContactInformation>
+  <Fees>none</Fees>
+
+  <AccessConstraints>none</AccessConstraints>
+</Service>
+<Capability>
+  <Request>
+    <GetCapabilities>
+      <Format>application/vnd.ogc.wms_xml</Format>
+      <DCPType>
+        <HTTP>
+          <Get>
+
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname:port/path" />
+          </Get>
+          <Post>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname:port/path" />
+          </Post>
+        </HTTP>
+      </DCPType>
+
+    </GetCapabilities>
+    <GetMap>
+      <Format>image/gif</Format>
+      <Format>image/png</Format>
+      <Format>image/jpeg</Format>
+      <DCPType>
+        <HTTP>
+
+          <Get>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname:port/path" />
+          </Get>
+        </HTTP>
+      </DCPType>
+    </GetMap>
+    <GetFeatureInfo>
+      <Format>application/vnd.ogc.gml</Format>
+
+      <Format>text/plain</Format>
+      <Format>text/html</Format>
+      <DCPType>
+        <HTTP>
+          <Get>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname:port/path" />
+          </Get>
+        </HTTP>
+
+      </DCPType>
+    </GetFeatureInfo>
+    <DescribeLayer>
+      <Format>application/vnd.ogc.gml</Format>
+      <DCPType>
+        <HTTP>
+          <Get>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname:port/path" />
+
+          </Get>
+        </HTTP>
+      </DCPType>
+    </DescribeLayer>
+  </Request>
+  <Exception>
+    <Format>application/vnd.ogc.se_xml</Format>
+    <Format>application/vnd.ogc.se_inimage</Format>
+
+    <Format>application/vnd.ogc.se_blank</Format>
+  </Exception>
+  <VendorSpecificCapabilities />
+  <UserDefinedSymbolization SupportSLD="1" UserLayer="1" UserStyle="1"
+    RemoteWFS="1" />
+
+  <Layer>
+    <Title>Acme Corp. Map Server</Title>
+    <SRS>EPSG:4326</SRS>
+    <AuthorityURL name="DIF_ID">
+      <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+       xlink:href="http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html" />
+    </AuthorityURL>
+
+
+    <Layer>
+      <Name>ROADS_RIVERS</Name> 
+      <Title>Roads and Rivers</Title>
+      <SRS>EPSG:26986</SRS> 
+      <LatLonBoundingBox minx="-71.63" miny="41.75" maxx="-70.78" maxy="42.90"/>
+      <BoundingBox SRS="EPSG:4326"
+       minx="-71.63" miny="41.75" maxx="-70.78" maxy="42.90" resx="0.01" resy="0.01"/>
+
+      <BoundingBox SRS="EPSG:26986"
+       minx="189000" miny="834000" maxx="285000" maxy="962000" resx="1" resy="1" />
+      <Attribution>
+        <Title>State College University</Title>
+        <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+         xlink:href="http://www.university.edu/" />
+        <LogoURL width="100" height="100">
+          <Format>image/gif</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/icons/logo.gif" />
+
+        </LogoURL>
+      </Attribution>
+      <Identifier authority="DIF_ID">123456</Identifier>
+      <FeatureListURL>
+        <Format>application/vnd.ogc.se_xml</Format>
+        <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+         xlink:href="http://www.university.edu/data/roads_rivers.gml" />
+      </FeatureListURL>
+
+      <Style>
+        <Name>USGS</Name>
+        <Title>USGS Topo Map Style</Title>
+        <Abstract>Features are shown in a style like that used in USGS topographic maps.</Abstract>
+        <LegendURL width="72" height="72">
+          <Format>image/gif</Format>
+
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/legends/usgs.gif" />
+        </LegendURL>
+        <StyleSheetURL>
+          <Format>text/xsl</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/stylesheets/usgs.xsl" />
+        </StyleSheetURL>
+      </Style>
+
+      <ScaleHint min="4000" max="35000"></ScaleHint>
+
+
+      <Layer queryable="1">
+    <Name>ROADS_1M</Name> 
+    <Title>Roads at 1:1M scale</Title>
+    <Abstract>Roads at a scale of 1 to 1 million.</Abstract>
+    <KeywordList>
+          <Keyword>road</Keyword>
+
+          <Keyword>transportation</Keyword>
+          <Keyword>atlas</Keyword>
+    </KeywordList>
+    <Identifier authority="DIF_ID">123456</Identifier>
+    <MetadataURL type="FGDC">
+          <Format>text/plain</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/metadata/roads.txt" />
+        </MetadataURL>
+    <MetadataURL type="FGDC">
+           <Format>text/xml</Format>
+           <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+            xlink:type="simple"
+            xlink:href="http://www.university.edu/metadata/roads.xml" />
+        </MetadataURL>
+    <Style>
+
+      <Name>ATLAS</Name>
+      <Title>Road atlas style</Title>
+      <Abstract>Roads are shown in a style like that used in a commercial road atlas.</Abstract>
+        <LegendURL width="72" height="72">
+          <Format>image/gif</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/legends/atlas.gif" />
+        </LegendURL>
+
+    </Style>
+      <ScaleHint min="0.395998292216226" max="98.9995730540565" />
+      </Layer>
+      <Layer queryable="1">
+    <Name>RIVERS_1M</Name>
+    <Title>Rivers at 1:1M scale</Title>
+    <Abstract>Rivers at a scale of 1 to 1 million.</Abstract>
+    <KeywordList>
+
+          <Keyword>river</Keyword>
+          <Keyword>canal</Keyword>
+          <Keyword>waterway</Keyword>
+    </KeywordList>
+      </Layer>
+    </Layer>
+    <Layer queryable="1">
+
+      <Title>Weather Forecast Data</Title>
+      <SRS>EPSG:4326</SRS>
+      <LatLonBoundingBox minx="-180" miny="-90" maxx="180" maxy="90" />
+      <Dimension name="time" units="ISO8601" />
+      <Extent name="time" default="2000-08-22">1999-01-01/2000-08-22/P1D</Extent>
+
+      <Layer>
+    <Name>Clouds</Name> 
+    <Title>Forecast cloud cover</Title>
+      </Layer>
+
+      <Layer>
+    <Name>Temperature</Name> 
+    <Title>Forecast temperature</Title>
+      </Layer>
+
+      <Layer>
+    <Name>Pressure</Name> 
+    <Title>Forecast barometric pressure</Title>
+         <Dimension name="time" units="ISO8601" />
+         <Dimension name="elevation" units="EPSG:5030" />
+         <Extent name="time" default="2000-08-22">1999-01-01/2000-08-22/P1D</Extent>
+         <Extent name="elevation" default="0" nearestValue="1">0,1000,3000,5000,10000</Extent>
+      </Layer>
+
+    </Layer>
+
+    <Layer opaque="1" noSubsets="1" fixedWidth="512" fixedHeight="256">
+      <Name>ozone_image</Name>
+      <Title>Global ozone distribution (1992)</Title>
+      <LatLonBoundingBox minx="-180" miny="-90" maxx="180" maxy="90" />
+      <Extent name="time" default="1992">1992</Extent>
+    </Layer>
+
+    <Layer cascaded="1">
+      <Name>population</Name>
+      <Title>World population, annual</Title>
+      <LatLonBoundingBox minx="-180" miny="-90" maxx="180" maxy="90" />
+      <Extent name="time" default="2000">1990/2000/P1Y</Extent>
+    </Layer>
+
+  </Layer>
+
+
+</Capability>
+</WMT_MS_Capabilities>
+--></div>
+<!--
+GeoServer example below taken from
+http://publicus.opengeo.org/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities
+Changes:
+* fixed DTD URL (publicus is no longer available)
+* removed comments
+-->
+<div id="gssample"><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE WMT_MS_Capabilities SYSTEM "http://schemas.opengis.net/wms/1.1.1/capabilities_1_1_1.dtd">
+<WMT_MS_Capabilities version="1.1.1" updateSequence="57">
+  <Service>
+    <Name>OGC:WMS</Name>
+    <Title>GeoServer Web Map Service</Title>
+    <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
+    <KeywordList>
+      <Keyword>WFS</Keyword>
+      <Keyword>WMS</Keyword>
+      <Keyword>GEOSERVER</Keyword>
+    </KeywordList>
+    <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms"/>
+    <ContactInformation>
+      <ContactPersonPrimary>
+        <ContactPerson>Claudius Ptolomaeus</ContactPerson>
+        <ContactOrganization>The ancient geographes INC</ContactOrganization>
+      </ContactPersonPrimary>
+      <ContactPosition>Chief geographer</ContactPosition>
+      <ContactAddress>
+        <AddressType>Work</AddressType>
+        <Address/>
+        <City>Alexandria</City>
+        <StateOrProvince/>
+        <PostCode/>
+        <Country>Egypt</Country>
+      </ContactAddress>
+      <ContactVoiceTelephone/>
+      <ContactFacsimileTelephone/>
+      <ContactElectronicMailAddress>claudius.ptolomaeus at gmail.com</ContactElectronicMailAddress>
+    </ContactInformation>
+    <Fees>NONE</Fees>
+    <AccessConstraints>NONE</AccessConstraints>
+  </Service>
+  <Capability>
+    <Request>
+      <GetCapabilities>
+        <Format>application/vnd.ogc.wms_xml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+            <Post>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Post>
+          </HTTP>
+        </DCPType>
+      </GetCapabilities>
+      <GetMap>
+        <Format>image/png</Format>
+        <Format>application/atom xml</Format>
+        <Format>application/atom+xml</Format>
+        <Format>application/openlayers</Format>
+        <Format>application/pdf</Format>
+        <Format>application/rss xml</Format>
+        <Format>application/rss+xml</Format>
+        <Format>application/vnd.google-earth.kml</Format>
+        <Format>application/vnd.google-earth.kml xml</Format>
+        <Format>application/vnd.google-earth.kml+xml</Format>
+        <Format>application/vnd.google-earth.kmz</Format>
+        <Format>application/vnd.google-earth.kmz xml</Format>
+        <Format>application/vnd.google-earth.kmz+xml</Format>
+        <Format>atom</Format>
+        <Format>image/geotiff</Format>
+        <Format>image/geotiff8</Format>
+        <Format>image/gif</Format>
+        <Format>image/jpeg</Format>
+        <Format>image/png8</Format>
+        <Format>image/svg</Format>
+        <Format>image/svg xml</Format>
+        <Format>image/svg+xml</Format>
+        <Format>image/tiff</Format>
+        <Format>image/tiff8</Format>
+        <Format>kml</Format>
+        <Format>kmz</Format>
+        <Format>openlayers</Format>
+        <Format>rss</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </GetMap>
+      <GetFeatureInfo>
+        <Format>text/plain</Format>
+        <Format>text/html</Format>
+        <Format>application/vnd.ogc.gml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+            <Post>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Post>
+          </HTTP>
+        </DCPType>
+      </GetFeatureInfo>
+      <DescribeLayer>
+        <Format>application/vnd.ogc.wms_xml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </DescribeLayer>
+      <GetLegendGraphic>
+        <Format>image/png</Format>
+        <Format>image/jpeg</Format>
+        <Format>image/gif</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </GetLegendGraphic>
+    </Request>
+    <Exception>
+      <Format>application/vnd.ogc.se_xml</Format>
+    </Exception>
+    <UserDefinedSymbolization SupportSLD="1" UserLayer="1" UserStyle="1" RemoteWFS="1"/>
+    <Layer>
+      <Title>GeoServer Web Map Service</Title>
+      <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
+      <SRS>EPSG:WGS84(DD)</SRS>
+      <SRS>EPSG:2000</SRS>
+      <SRS>EPSG:2001</SRS>
+      <SRS>EPSG:2002</SRS>
+      <SRS>EPSG:2003</SRS>
+      <SRS>EPSG:2004</SRS>
+      <SRS>EPSG:2005</SRS>
+      <SRS>EPSG:2006</SRS>
+      <SRS>EPSG:2007</SRS>
+      <SRS>EPSG:2008</SRS>
+      <SRS>EPSG:2009</SRS>
+      <SRS>EPSG:2010</SRS>
+      <SRS>EPSG:2011</SRS>
+      <SRS>EPSG:2012</SRS>
+      <SRS>EPSG:2013</SRS>
+      <SRS>EPSG:2014</SRS>
+      <SRS>EPSG:2015</SRS>
+      <SRS>EPSG:2016</SRS>
+      <SRS>EPSG:2017</SRS>
+      <SRS>EPSG:2018</SRS>
+      <SRS>EPSG:2019</SRS>
+      <SRS>EPSG:2020</SRS>
+      <SRS>EPSG:2021</SRS>
+      <SRS>EPSG:2022</SRS>
+      <SRS>EPSG:2023</SRS>
+      <SRS>EPSG:2024</SRS>
+      <SRS>EPSG:2025</SRS>
+      <SRS>EPSG:2026</SRS>
+      <SRS>EPSG:2027</SRS>
+      <SRS>EPSG:2028</SRS>
+      <SRS>EPSG:2029</SRS>
+      <SRS>EPSG:2030</SRS>
+      <SRS>EPSG:2031</SRS>
+      <SRS>EPSG:2032</SRS>
+      <SRS>EPSG:2033</SRS>
+      <SRS>EPSG:2034</SRS>
+      <SRS>EPSG:2035</SRS>
+      <SRS>EPSG:2036</SRS>
+      <SRS>EPSG:2037</SRS>
+      <SRS>EPSG:2038</SRS>
+      <SRS>EPSG:2039</SRS>
+      <SRS>EPSG:2040</SRS>
+      <SRS>EPSG:2041</SRS>
+      <SRS>EPSG:2042</SRS>
+      <SRS>EPSG:2043</SRS>
+      <SRS>EPSG:2044</SRS>
+      <SRS>EPSG:2045</SRS>
+      <SRS>EPSG:2046</SRS>
+      <SRS>EPSG:2047</SRS>
+      <SRS>EPSG:2048</SRS>
+      <SRS>EPSG:2049</SRS>
+      <SRS>EPSG:2050</SRS>
+      <SRS>EPSG:2051</SRS>
+      <SRS>EPSG:2052</SRS>
+      <SRS>EPSG:2053</SRS>
+      <SRS>EPSG:2054</SRS>
+      <SRS>EPSG:2055</SRS>
+      <SRS>EPSG:2056</SRS>
+      <SRS>EPSG:2057</SRS>
+      <SRS>EPSG:2058</SRS>
+      <SRS>EPSG:2059</SRS>
+      <SRS>EPSG:2060</SRS>
+      <SRS>EPSG:2061</SRS>
+      <SRS>EPSG:2062</SRS>
+      <SRS>EPSG:2063</SRS>
+      <SRS>EPSG:2064</SRS>
+      <SRS>EPSG:2065</SRS>
+      <SRS>EPSG:2066</SRS>
+      <SRS>EPSG:2067</SRS>
+      <SRS>EPSG:2068</SRS>
+      <SRS>EPSG:2069</SRS>
+      <SRS>EPSG:2070</SRS>
+      <SRS>EPSG:2071</SRS>
+      <SRS>EPSG:2072</SRS>
+      <SRS>EPSG:2073</SRS>
+      <SRS>EPSG:2074</SRS>
+      <SRS>EPSG:2075</SRS>
+      <SRS>EPSG:2076</SRS>
+      <SRS>EPSG:2077</SRS>
+      <SRS>EPSG:2078</SRS>
+      <SRS>EPSG:2079</SRS>
+      <SRS>EPSG:2080</SRS>
+      <SRS>EPSG:2081</SRS>
+      <SRS>EPSG:2082</SRS>
+      <SRS>EPSG:2083</SRS>
+      <SRS>EPSG:2084</SRS>
+      <SRS>EPSG:2085</SRS>
+      <SRS>EPSG:2086</SRS>
+      <SRS>EPSG:2087</SRS>
+      <SRS>EPSG:2088</SRS>
+      <SRS>EPSG:2089</SRS>
+      <SRS>EPSG:2090</SRS>
+      <SRS>EPSG:2091</SRS>
+      <SRS>EPSG:2092</SRS>
+      <SRS>EPSG:2093</SRS>
+      <SRS>EPSG:2094</SRS>
+      <SRS>EPSG:2095</SRS>
+      <SRS>EPSG:2096</SRS>
+      <SRS>EPSG:2097</SRS>
+      <SRS>EPSG:2098</SRS>
+      <SRS>EPSG:2099</SRS>
+      <SRS>EPSG:2100</SRS>
+      <SRS>EPSG:2101</SRS>
+      <SRS>EPSG:2102</SRS>
+      <SRS>EPSG:2103</SRS>
+      <SRS>EPSG:2104</SRS>
+      <SRS>EPSG:2105</SRS>
+      <SRS>EPSG:2106</SRS>
+      <SRS>EPSG:2107</SRS>
+      <SRS>EPSG:2108</SRS>
+      <SRS>EPSG:2109</SRS>
+      <SRS>EPSG:2110</SRS>
+      <SRS>EPSG:2111</SRS>
+      <SRS>EPSG:2112</SRS>
+      <SRS>EPSG:2113</SRS>
+      <SRS>EPSG:2114</SRS>
+      <SRS>EPSG:2115</SRS>
+      <SRS>EPSG:2116</SRS>
+      <SRS>EPSG:2117</SRS>
+      <SRS>EPSG:2118</SRS>
+      <SRS>EPSG:2119</SRS>
+      <SRS>EPSG:2120</SRS>
+      <SRS>EPSG:2121</SRS>
+      <SRS>EPSG:2122</SRS>
+      <SRS>EPSG:2123</SRS>
+      <SRS>EPSG:2124</SRS>
+      <SRS>EPSG:2125</SRS>
+      <SRS>EPSG:2126</SRS>
+      <SRS>EPSG:2127</SRS>
+      <SRS>EPSG:2128</SRS>
+      <SRS>EPSG:2129</SRS>
+      <SRS>EPSG:2130</SRS>
+      <SRS>EPSG:2131</SRS>
+      <SRS>EPSG:2132</SRS>
+      <SRS>EPSG:2133</SRS>
+      <SRS>EPSG:2134</SRS>
+      <SRS>EPSG:2135</SRS>
+      <SRS>EPSG:2136</SRS>
+      <SRS>EPSG:2137</SRS>
+      <SRS>EPSG:2138</SRS>
+      <SRS>EPSG:2139</SRS>
+      <SRS>EPSG:2140</SRS>
+      <SRS>EPSG:2141</SRS>
+      <SRS>EPSG:2142</SRS>
+      <SRS>EPSG:2143</SRS>
+      <SRS>EPSG:2144</SRS>
+      <SRS>EPSG:2145</SRS>
+      <SRS>EPSG:2146</SRS>
+      <SRS>EPSG:2147</SRS>
+      <SRS>EPSG:2148</SRS>
+      <SRS>EPSG:2149</SRS>
+      <SRS>EPSG:2150</SRS>
+      <SRS>EPSG:2151</SRS>
+      <SRS>EPSG:2152</SRS>
+      <SRS>EPSG:2153</SRS>
+      <SRS>EPSG:2154</SRS>
+      <SRS>EPSG:2155</SRS>
+      <SRS>EPSG:2156</SRS>
+      <SRS>EPSG:2157</SRS>
+      <SRS>EPSG:2158</SRS>
+      <SRS>EPSG:2159</SRS>
+      <SRS>EPSG:2160</SRS>
+      <SRS>EPSG:2161</SRS>
+      <SRS>EPSG:2162</SRS>
+      <SRS>EPSG:2163</SRS>
+      <SRS>EPSG:2164</SRS>
+      <SRS>EPSG:2165</SRS>
+      <SRS>EPSG:2166</SRS>
+      <SRS>EPSG:2167</SRS>
+      <SRS>EPSG:2168</SRS>
+      <SRS>EPSG:2169</SRS>
+      <SRS>EPSG:2170</SRS>
+      <SRS>EPSG:2171</SRS>
+      <SRS>EPSG:2172</SRS>
+      <SRS>EPSG:2173</SRS>
+      <SRS>EPSG:2174</SRS>
+      <SRS>EPSG:2175</SRS>
+      <SRS>EPSG:2176</SRS>
+      <SRS>EPSG:2177</SRS>
+      <SRS>EPSG:2178</SRS>
+      <SRS>EPSG:2179</SRS>
+      <SRS>EPSG:2180</SRS>
+      <SRS>EPSG:2188</SRS>
+      <SRS>EPSG:2189</SRS>
+      <SRS>EPSG:2190</SRS>
+      <SRS>EPSG:2191</SRS>
+      <SRS>EPSG:2192</SRS>
+      <SRS>EPSG:2193</SRS>
+      <SRS>EPSG:2194</SRS>
+      <SRS>EPSG:2195</SRS>
+      <SRS>EPSG:2196</SRS>
+      <SRS>EPSG:2197</SRS>
+      <SRS>EPSG:2198</SRS>
+      <SRS>EPSG:2199</SRS>
+      <SRS>EPSG:2200</SRS>
+      <SRS>EPSG:2201</SRS>
+      <SRS>EPSG:2202</SRS>
+      <SRS>EPSG:2203</SRS>
+      <SRS>EPSG:2204</SRS>
+      <SRS>EPSG:2205</SRS>
+      <SRS>EPSG:2206</SRS>
+      <SRS>EPSG:2207</SRS>
+      <SRS>EPSG:2208</SRS>
+      <SRS>EPSG:2209</SRS>
+      <SRS>EPSG:2210</SRS>
+      <SRS>EPSG:2211</SRS>
+      <SRS>EPSG:2212</SRS>
+      <SRS>EPSG:2213</SRS>
+      <SRS>EPSG:2214</SRS>
+      <SRS>EPSG:2215</SRS>
+      <SRS>EPSG:2216</SRS>
+      <SRS>EPSG:2217</SRS>
+      <SRS>EPSG:2218</SRS>
+      <SRS>EPSG:2219</SRS>
+      <SRS>EPSG:2220</SRS>
+      <SRS>EPSG:2221</SRS>
+      <SRS>EPSG:2222</SRS>
+      <SRS>EPSG:2223</SRS>
+      <SRS>EPSG:2224</SRS>
+      <SRS>EPSG:2225</SRS>
+      <SRS>EPSG:2226</SRS>
+      <SRS>EPSG:2227</SRS>
+      <SRS>EPSG:2228</SRS>
+      <SRS>EPSG:2229</SRS>
+      <SRS>EPSG:2230</SRS>
+      <SRS>EPSG:2231</SRS>
+      <SRS>EPSG:2232</SRS>
+      <SRS>EPSG:2233</SRS>
+      <SRS>EPSG:2234</SRS>
+      <SRS>EPSG:2235</SRS>
+      <SRS>EPSG:2236</SRS>
+      <SRS>EPSG:2237</SRS>
+      <SRS>EPSG:2238</SRS>
+      <SRS>EPSG:2239</SRS>
+      <SRS>EPSG:2240</SRS>
+      <SRS>EPSG:2241</SRS>
+      <SRS>EPSG:2242</SRS>
+      <SRS>EPSG:2243</SRS>
+      <SRS>EPSG:2244</SRS>
+      <SRS>EPSG:2245</SRS>
+      <SRS>EPSG:2246</SRS>
+      <SRS>EPSG:2247</SRS>
+      <SRS>EPSG:2248</SRS>
+      <SRS>EPSG:2249</SRS>
+      <SRS>EPSG:2250</SRS>
+      <SRS>EPSG:2251</SRS>
+      <SRS>EPSG:2252</SRS>
+      <SRS>EPSG:2253</SRS>
+      <SRS>EPSG:2254</SRS>
+      <SRS>EPSG:2255</SRS>
+      <SRS>EPSG:2256</SRS>
+      <SRS>EPSG:2257</SRS>
+      <SRS>EPSG:2258</SRS>
+      <SRS>EPSG:2259</SRS>
+      <SRS>EPSG:2260</SRS>
+      <SRS>EPSG:2261</SRS>
+      <SRS>EPSG:2262</SRS>
+      <SRS>EPSG:2263</SRS>
+      <SRS>EPSG:2264</SRS>
+      <SRS>EPSG:2265</SRS>
+      <SRS>EPSG:2266</SRS>
+      <SRS>EPSG:2267</SRS>
+      <SRS>EPSG:2268</SRS>
+      <SRS>EPSG:2269</SRS>
+      <SRS>EPSG:2270</SRS>
+      <SRS>EPSG:2271</SRS>
+      <SRS>EPSG:2272</SRS>
+      <SRS>EPSG:2273</SRS>
+      <SRS>EPSG:2274</SRS>
+      <SRS>EPSG:2275</SRS>
+      <SRS>EPSG:2276</SRS>
+      <SRS>EPSG:2277</SRS>
+      <SRS>EPSG:2278</SRS>
+      <SRS>EPSG:2279</SRS>
+      <SRS>EPSG:2280</SRS>
+      <SRS>EPSG:2281</SRS>
+      <SRS>EPSG:2282</SRS>
+      <SRS>EPSG:2283</SRS>
+      <SRS>EPSG:2284</SRS>
+      <SRS>EPSG:2285</SRS>
+      <SRS>EPSG:2286</SRS>
+      <SRS>EPSG:2287</SRS>
+      <SRS>EPSG:2288</SRS>
+      <SRS>EPSG:2289</SRS>
+      <SRS>EPSG:2290</SRS>
+      <SRS>EPSG:2291</SRS>
+      <SRS>EPSG:2292</SRS>
+      <SRS>EPSG:2294</SRS>
+      <SRS>EPSG:2295</SRS>
+      <SRS>EPSG:2296</SRS>
+      <SRS>EPSG:2297</SRS>
+      <SRS>EPSG:2298</SRS>
+      <SRS>EPSG:2299</SRS>
+      <SRS>EPSG:2300</SRS>
+      <SRS>EPSG:2301</SRS>
+      <SRS>EPSG:2302</SRS>
+      <SRS>EPSG:2303</SRS>
+      <SRS>EPSG:2304</SRS>
+      <SRS>EPSG:2305</SRS>
+      <SRS>EPSG:2306</SRS>
+      <SRS>EPSG:2307</SRS>
+      <SRS>EPSG:2308</SRS>
+      <SRS>EPSG:2309</SRS>
+      <SRS>EPSG:2310</SRS>
+      <SRS>EPSG:2311</SRS>
+      <SRS>EPSG:2312</SRS>
+      <SRS>EPSG:2313</SRS>
+      <SRS>EPSG:2314</SRS>
+      <SRS>EPSG:2315</SRS>
+      <SRS>EPSG:2316</SRS>
+      <SRS>EPSG:2317</SRS>
+      <SRS>EPSG:2318</SRS>
+      <SRS>EPSG:2319</SRS>
+      <SRS>EPSG:2320</SRS>
+      <SRS>EPSG:2321</SRS>
+      <SRS>EPSG:2322</SRS>
+      <SRS>EPSG:2323</SRS>
+      <SRS>EPSG:2324</SRS>
+      <SRS>EPSG:2325</SRS>
+      <SRS>EPSG:2326</SRS>
+      <SRS>EPSG:2327</SRS>
+      <SRS>EPSG:2328</SRS>
+      <SRS>EPSG:2329</SRS>
+      <SRS>EPSG:2330</SRS>
+      <SRS>EPSG:2331</SRS>
+      <SRS>EPSG:2332</SRS>
+      <SRS>EPSG:2333</SRS>
+      <SRS>EPSG:2334</SRS>
+      <SRS>EPSG:2335</SRS>
+      <SRS>EPSG:2336</SRS>
+      <SRS>EPSG:2337</SRS>
+      <SRS>EPSG:2338</SRS>
+      <SRS>EPSG:2339</SRS>
+      <SRS>EPSG:2340</SRS>
+      <SRS>EPSG:2341</SRS>
+      <SRS>EPSG:2342</SRS>
+      <SRS>EPSG:2343</SRS>
+      <SRS>EPSG:2344</SRS>
+      <SRS>EPSG:2345</SRS>
+      <SRS>EPSG:2346</SRS>
+      <SRS>EPSG:2347</SRS>
+      <SRS>EPSG:2348</SRS>
+      <SRS>EPSG:2349</SRS>
+      <SRS>EPSG:2350</SRS>
+      <SRS>EPSG:2351</SRS>
+      <SRS>EPSG:2352</SRS>
+      <SRS>EPSG:2353</SRS>
+      <SRS>EPSG:2354</SRS>
+      <SRS>EPSG:2355</SRS>
+      <SRS>EPSG:2356</SRS>
+      <SRS>EPSG:2357</SRS>
+      <SRS>EPSG:2358</SRS>
+      <SRS>EPSG:2359</SRS>
+      <SRS>EPSG:2360</SRS>
+      <SRS>EPSG:2361</SRS>
+      <SRS>EPSG:2362</SRS>
+      <SRS>EPSG:2363</SRS>
+      <SRS>EPSG:2364</SRS>
+      <SRS>EPSG:2365</SRS>
+      <SRS>EPSG:2366</SRS>
+      <SRS>EPSG:2367</SRS>
+      <SRS>EPSG:2368</SRS>
+      <SRS>EPSG:2369</SRS>
+      <SRS>EPSG:2370</SRS>
+      <SRS>EPSG:2371</SRS>
+      <SRS>EPSG:2372</SRS>
+      <SRS>EPSG:2373</SRS>
+      <SRS>EPSG:2374</SRS>
+      <SRS>EPSG:2375</SRS>
+      <SRS>EPSG:2376</SRS>
+      <SRS>EPSG:2377</SRS>
+      <SRS>EPSG:2378</SRS>
+      <SRS>EPSG:2379</SRS>
+      <SRS>EPSG:2380</SRS>
+      <SRS>EPSG:2381</SRS>
+      <SRS>EPSG:2382</SRS>
+      <SRS>EPSG:2383</SRS>
+      <SRS>EPSG:2384</SRS>
+      <SRS>EPSG:2385</SRS>
+      <SRS>EPSG:2386</SRS>
+      <SRS>EPSG:2387</SRS>
+      <SRS>EPSG:2388</SRS>
+      <SRS>EPSG:2389</SRS>
+      <SRS>EPSG:2390</SRS>
+      <SRS>EPSG:2391</SRS>
+      <SRS>EPSG:2392</SRS>
+      <SRS>EPSG:2393</SRS>
+      <SRS>EPSG:2394</SRS>
+      <SRS>EPSG:2395</SRS>
+      <SRS>EPSG:2396</SRS>
+      <SRS>EPSG:2397</SRS>
+      <SRS>EPSG:2398</SRS>
+      <SRS>EPSG:2399</SRS>
+      <SRS>EPSG:2400</SRS>
+      <SRS>EPSG:2401</SRS>
+      <SRS>EPSG:2402</SRS>
+      <SRS>EPSG:2403</SRS>
+      <SRS>EPSG:2404</SRS>
+      <SRS>EPSG:2405</SRS>
+      <SRS>EPSG:2406</SRS>
+      <SRS>EPSG:2407</SRS>
+      <SRS>EPSG:2408</SRS>
+      <SRS>EPSG:2409</SRS>
+      <SRS>EPSG:2410</SRS>
+      <SRS>EPSG:2411</SRS>
+      <SRS>EPSG:2412</SRS>
+      <SRS>EPSG:2413</SRS>
+      <SRS>EPSG:2414</SRS>
+      <SRS>EPSG:2415</SRS>
+      <SRS>EPSG:2416</SRS>
+      <SRS>EPSG:2417</SRS>
+      <SRS>EPSG:2418</SRS>
+      <SRS>EPSG:2419</SRS>
+      <SRS>EPSG:2420</SRS>
+      <SRS>EPSG:2421</SRS>
+      <SRS>EPSG:2422</SRS>
+      <SRS>EPSG:2423</SRS>
+      <SRS>EPSG:2424</SRS>
+      <SRS>EPSG:2425</SRS>
+      <SRS>EPSG:2426</SRS>
+      <SRS>EPSG:2427</SRS>
+      <SRS>EPSG:2428</SRS>
+      <SRS>EPSG:2429</SRS>
+      <SRS>EPSG:2430</SRS>
+      <SRS>EPSG:2431</SRS>
+      <SRS>EPSG:2432</SRS>
+      <SRS>EPSG:2433</SRS>
+      <SRS>EPSG:2434</SRS>
+      <SRS>EPSG:2435</SRS>
+      <SRS>EPSG:2436</SRS>
+      <SRS>EPSG:2437</SRS>
+      <SRS>EPSG:2438</SRS>
+      <SRS>EPSG:2439</SRS>
+      <SRS>EPSG:2440</SRS>
+      <SRS>EPSG:2441</SRS>
+      <SRS>EPSG:2442</SRS>
+      <SRS>EPSG:2443</SRS>
+      <SRS>EPSG:2444</SRS>
+      <SRS>EPSG:2445</SRS>
+      <SRS>EPSG:2446</SRS>
+      <SRS>EPSG:2447</SRS>
+      <SRS>EPSG:2448</SRS>
+      <SRS>EPSG:2449</SRS>
+      <SRS>EPSG:2450</SRS>
+      <SRS>EPSG:2451</SRS>
+      <SRS>EPSG:2452</SRS>
+      <SRS>EPSG:2453</SRS>
+      <SRS>EPSG:2454</SRS>
+      <SRS>EPSG:2455</SRS>
+      <SRS>EPSG:2456</SRS>
+      <SRS>EPSG:2457</SRS>
+      <SRS>EPSG:2458</SRS>
+      <SRS>EPSG:2459</SRS>
+      <SRS>EPSG:2460</SRS>
+      <SRS>EPSG:2461</SRS>
+      <SRS>EPSG:2462</SRS>
+      <SRS>EPSG:2463</SRS>
+      <SRS>EPSG:2464</SRS>
+      <SRS>EPSG:2465</SRS>
+      <SRS>EPSG:2466</SRS>
+      <SRS>EPSG:2467</SRS>
+      <SRS>EPSG:2468</SRS>
+      <SRS>EPSG:2469</SRS>
+      <SRS>EPSG:2470</SRS>
+      <SRS>EPSG:2471</SRS>
+      <SRS>EPSG:2472</SRS>
+      <SRS>EPSG:2473</SRS>
+      <SRS>EPSG:2474</SRS>
+      <SRS>EPSG:2475</SRS>
+      <SRS>EPSG:2476</SRS>
+      <SRS>EPSG:2477</SRS>
+      <SRS>EPSG:2478</SRS>
+      <SRS>EPSG:2479</SRS>
+      <SRS>EPSG:2480</SRS>
+      <SRS>EPSG:2481</SRS>
+      <SRS>EPSG:2482</SRS>
+      <SRS>EPSG:2483</SRS>
+      <SRS>EPSG:2484</SRS>
+      <SRS>EPSG:2485</SRS>
+      <SRS>EPSG:2486</SRS>
+      <SRS>EPSG:2487</SRS>
+      <SRS>EPSG:2488</SRS>
+      <SRS>EPSG:2489</SRS>
+      <SRS>EPSG:2490</SRS>
+      <SRS>EPSG:2491</SRS>
+      <SRS>EPSG:2492</SRS>
+      <SRS>EPSG:2493</SRS>
+      <SRS>EPSG:2494</SRS>
+      <SRS>EPSG:2495</SRS>
+      <SRS>EPSG:2496</SRS>
+      <SRS>EPSG:2497</SRS>
+      <SRS>EPSG:2498</SRS>
+      <SRS>EPSG:2499</SRS>
+      <SRS>EPSG:2500</SRS>
+      <SRS>EPSG:2501</SRS>
+      <SRS>EPSG:2502</SRS>
+      <SRS>EPSG:2503</SRS>
+      <SRS>EPSG:2504</SRS>
+      <SRS>EPSG:2505</SRS>
+      <SRS>EPSG:2506</SRS>
+      <SRS>EPSG:2507</SRS>
+      <SRS>EPSG:2508</SRS>
+      <SRS>EPSG:2509</SRS>
+      <SRS>EPSG:2510</SRS>
+      <SRS>EPSG:2511</SRS>
+      <SRS>EPSG:2512</SRS>
+      <SRS>EPSG:2513</SRS>
+      <SRS>EPSG:2514</SRS>
+      <SRS>EPSG:2515</SRS>
+      <SRS>EPSG:2516</SRS>
+      <SRS>EPSG:2517</SRS>
+      <SRS>EPSG:2518</SRS>
+      <SRS>EPSG:2519</SRS>
+      <SRS>EPSG:2520</SRS>
+      <SRS>EPSG:2521</SRS>
+      <SRS>EPSG:2522</SRS>
+      <SRS>EPSG:2523</SRS>
+      <SRS>EPSG:2524</SRS>
+      <SRS>EPSG:2525</SRS>
+      <SRS>EPSG:2526</SRS>
+      <SRS>EPSG:2527</SRS>
+      <SRS>EPSG:2528</SRS>
+      <SRS>EPSG:2529</SRS>
+      <SRS>EPSG:2530</SRS>
+      <SRS>EPSG:2531</SRS>
+      <SRS>EPSG:2532</SRS>
+      <SRS>EPSG:2533</SRS>
+      <SRS>EPSG:2534</SRS>
+      <SRS>EPSG:2535</SRS>
+      <SRS>EPSG:2536</SRS>
+      <SRS>EPSG:2537</SRS>
+      <SRS>EPSG:2538</SRS>
+      <SRS>EPSG:2539</SRS>
+      <SRS>EPSG:2540</SRS>
+      <SRS>EPSG:2541</SRS>
+      <SRS>EPSG:2542</SRS>
+      <SRS>EPSG:2543</SRS>
+      <SRS>EPSG:2544</SRS>
+      <SRS>EPSG:2545</SRS>
+      <SRS>EPSG:2546</SRS>
+      <SRS>EPSG:2547</SRS>
+      <SRS>EPSG:2548</SRS>
+      <SRS>EPSG:2549</SRS>
+      <SRS>EPSG:2550</SRS>
+      <SRS>EPSG:2551</SRS>
+      <SRS>EPSG:2552</SRS>
+      <SRS>EPSG:2553</SRS>
+      <SRS>EPSG:2554</SRS>
+      <SRS>EPSG:2555</SRS>
+      <SRS>EPSG:2556</SRS>
+      <SRS>EPSG:2557</SRS>
+      <SRS>EPSG:2558</SRS>
+      <SRS>EPSG:2559</SRS>
+      <SRS>EPSG:2560</SRS>
+      <SRS>EPSG:2561</SRS>
+      <SRS>EPSG:2562</SRS>
+      <SRS>EPSG:2563</SRS>
+      <SRS>EPSG:2564</SRS>
+      <SRS>EPSG:2565</SRS>
+      <SRS>EPSG:2566</SRS>
+      <SRS>EPSG:2567</SRS>
+      <SRS>EPSG:2568</SRS>
+      <SRS>EPSG:2569</SRS>
+      <SRS>EPSG:2570</SRS>
+      <SRS>EPSG:2571</SRS>
+      <SRS>EPSG:2572</SRS>
+      <SRS>EPSG:2573</SRS>
+      <SRS>EPSG:2574</SRS>
+      <SRS>EPSG:2575</SRS>
+      <SRS>EPSG:2576</SRS>
+      <SRS>EPSG:2577</SRS>
+      <SRS>EPSG:2578</SRS>
+      <SRS>EPSG:2579</SRS>
+      <SRS>EPSG:2580</SRS>
+      <SRS>EPSG:2581</SRS>
+      <SRS>EPSG:2582</SRS>
+      <SRS>EPSG:2583</SRS>
+      <SRS>EPSG:2584</SRS>
+      <SRS>EPSG:2585</SRS>
+      <SRS>EPSG:2586</SRS>
+      <SRS>EPSG:2587</SRS>
+      <SRS>EPSG:2588</SRS>
+      <SRS>EPSG:2589</SRS>
+      <SRS>EPSG:2590</SRS>
+      <SRS>EPSG:2591</SRS>
+      <SRS>EPSG:2592</SRS>
+      <SRS>EPSG:2593</SRS>
+      <SRS>EPSG:2594</SRS>
+      <SRS>EPSG:2595</SRS>
+      <SRS>EPSG:2596</SRS>
+      <SRS>EPSG:2597</SRS>
+      <SRS>EPSG:2598</SRS>
+      <SRS>EPSG:2599</SRS>
+      <SRS>EPSG:2600</SRS>
+      <SRS>EPSG:2601</SRS>
+      <SRS>EPSG:2602</SRS>
+      <SRS>EPSG:2603</SRS>
+      <SRS>EPSG:2604</SRS>
+      <SRS>EPSG:2605</SRS>
+      <SRS>EPSG:2606</SRS>
+      <SRS>EPSG:2607</SRS>
+      <SRS>EPSG:2608</SRS>
+      <SRS>EPSG:2609</SRS>
+      <SRS>EPSG:2610</SRS>
+      <SRS>EPSG:2611</SRS>
+      <SRS>EPSG:2612</SRS>
+      <SRS>EPSG:2613</SRS>
+      <SRS>EPSG:2614</SRS>
+      <SRS>EPSG:2615</SRS>
+      <SRS>EPSG:2616</SRS>
+      <SRS>EPSG:2617</SRS>
+      <SRS>EPSG:2618</SRS>
+      <SRS>EPSG:2619</SRS>
+      <SRS>EPSG:2620</SRS>
+      <SRS>EPSG:2621</SRS>
+      <SRS>EPSG:2622</SRS>
+      <SRS>EPSG:2623</SRS>
+      <SRS>EPSG:2624</SRS>
+      <SRS>EPSG:2625</SRS>
+      <SRS>EPSG:2626</SRS>
+      <SRS>EPSG:2627</SRS>
+      <SRS>EPSG:2628</SRS>
+      <SRS>EPSG:2629</SRS>
+      <SRS>EPSG:2630</SRS>
+      <SRS>EPSG:2631</SRS>
+      <SRS>EPSG:2632</SRS>
+      <SRS>EPSG:2633</SRS>
+      <SRS>EPSG:2634</SRS>
+      <SRS>EPSG:2635</SRS>
+      <SRS>EPSG:2636</SRS>
+      <SRS>EPSG:2637</SRS>
+      <SRS>EPSG:2638</SRS>
+      <SRS>EPSG:2639</SRS>
+      <SRS>EPSG:2640</SRS>
+      <SRS>EPSG:2641</SRS>
+      <SRS>EPSG:2642</SRS>
+      <SRS>EPSG:2643</SRS>
+      <SRS>EPSG:2644</SRS>
+      <SRS>EPSG:2645</SRS>
+      <SRS>EPSG:2646</SRS>
+      <SRS>EPSG:2647</SRS>
+      <SRS>EPSG:2648</SRS>
+      <SRS>EPSG:2649</SRS>
+      <SRS>EPSG:2650</SRS>
+      <SRS>EPSG:2651</SRS>
+      <SRS>EPSG:2652</SRS>
+      <SRS>EPSG:2653</SRS>
+      <SRS>EPSG:2654</SRS>
+      <SRS>EPSG:2655</SRS>
+      <SRS>EPSG:2656</SRS>
+      <SRS>EPSG:2657</SRS>
+      <SRS>EPSG:2658</SRS>
+      <SRS>EPSG:2659</SRS>
+      <SRS>EPSG:2660</SRS>
+      <SRS>EPSG:2661</SRS>
+      <SRS>EPSG:2662</SRS>
+      <SRS>EPSG:2663</SRS>
+      <SRS>EPSG:2664</SRS>
+      <SRS>EPSG:2665</SRS>
+      <SRS>EPSG:2666</SRS>
+      <SRS>EPSG:2667</SRS>
+      <SRS>EPSG:2668</SRS>
+      <SRS>EPSG:2669</SRS>
+      <SRS>EPSG:2670</SRS>
+      <SRS>EPSG:2671</SRS>
+      <SRS>EPSG:2672</SRS>
+      <SRS>EPSG:2673</SRS>
+      <SRS>EPSG:2674</SRS>
+      <SRS>EPSG:2675</SRS>
+      <SRS>EPSG:2676</SRS>
+      <SRS>EPSG:2677</SRS>
+      <SRS>EPSG:2678</SRS>
+      <SRS>EPSG:2679</SRS>
+      <SRS>EPSG:2680</SRS>
+      <SRS>EPSG:2681</SRS>
+      <SRS>EPSG:2682</SRS>
+      <SRS>EPSG:2683</SRS>
+      <SRS>EPSG:2684</SRS>
+      <SRS>EPSG:2685</SRS>
+      <SRS>EPSG:2686</SRS>
+      <SRS>EPSG:2687</SRS>
+      <SRS>EPSG:2688</SRS>
+      <SRS>EPSG:2689</SRS>
+      <SRS>EPSG:2690</SRS>
+      <SRS>EPSG:2691</SRS>
+      <SRS>EPSG:2692</SRS>
+      <SRS>EPSG:2693</SRS>
+      <SRS>EPSG:2694</SRS>
+      <SRS>EPSG:2695</SRS>
+      <SRS>EPSG:2696</SRS>
+      <SRS>EPSG:2697</SRS>
+      <SRS>EPSG:2698</SRS>
+      <SRS>EPSG:2699</SRS>
+      <SRS>EPSG:2700</SRS>
+      <SRS>EPSG:2701</SRS>
+      <SRS>EPSG:2702</SRS>
+      <SRS>EPSG:2703</SRS>
+      <SRS>EPSG:2704</SRS>
+      <SRS>EPSG:2705</SRS>
+      <SRS>EPSG:2706</SRS>
+      <SRS>EPSG:2707</SRS>
+      <SRS>EPSG:2708</SRS>
+      <SRS>EPSG:2709</SRS>
+      <SRS>EPSG:2710</SRS>
+      <SRS>EPSG:2711</SRS>
+      <SRS>EPSG:2712</SRS>
+      <SRS>EPSG:2713</SRS>
+      <SRS>EPSG:2714</SRS>
+      <SRS>EPSG:2715</SRS>
+      <SRS>EPSG:2716</SRS>
+      <SRS>EPSG:2717</SRS>
+      <SRS>EPSG:2718</SRS>
+      <SRS>EPSG:2719</SRS>
+      <SRS>EPSG:2720</SRS>
+      <SRS>EPSG:2721</SRS>
+      <SRS>EPSG:2722</SRS>
+      <SRS>EPSG:2723</SRS>
+      <SRS>EPSG:2724</SRS>
+      <SRS>EPSG:2725</SRS>
+      <SRS>EPSG:2726</SRS>
+      <SRS>EPSG:2727</SRS>
+      <SRS>EPSG:2728</SRS>
+      <SRS>EPSG:2729</SRS>
+      <SRS>EPSG:2730</SRS>
+      <SRS>EPSG:2731</SRS>
+      <SRS>EPSG:2732</SRS>
+      <SRS>EPSG:2733</SRS>
+      <SRS>EPSG:2734</SRS>
+      <SRS>EPSG:2735</SRS>
+      <SRS>EPSG:2736</SRS>
+      <SRS>EPSG:2737</SRS>
+      <SRS>EPSG:2738</SRS>
+      <SRS>EPSG:2739</SRS>
+      <SRS>EPSG:2740</SRS>
+      <SRS>EPSG:2741</SRS>
+      <SRS>EPSG:2742</SRS>
+      <SRS>EPSG:2743</SRS>
+      <SRS>EPSG:2744</SRS>
+      <SRS>EPSG:2745</SRS>
+      <SRS>EPSG:2746</SRS>
+      <SRS>EPSG:2747</SRS>
+      <SRS>EPSG:2748</SRS>
+      <SRS>EPSG:2749</SRS>
+      <SRS>EPSG:2750</SRS>
+      <SRS>EPSG:2751</SRS>
+      <SRS>EPSG:2752</SRS>
+      <SRS>EPSG:2753</SRS>
+      <SRS>EPSG:2754</SRS>
+      <SRS>EPSG:2755</SRS>
+      <SRS>EPSG:2756</SRS>
+      <SRS>EPSG:2757</SRS>
+      <SRS>EPSG:2758</SRS>
+      <SRS>EPSG:2759</SRS>
+      <SRS>EPSG:2760</SRS>
+      <SRS>EPSG:2761</SRS>
+      <SRS>EPSG:2762</SRS>
+      <SRS>EPSG:2763</SRS>
+      <SRS>EPSG:2764</SRS>
+      <SRS>EPSG:2765</SRS>
+      <SRS>EPSG:2766</SRS>
+      <SRS>EPSG:2767</SRS>
+      <SRS>EPSG:2768</SRS>
+      <SRS>EPSG:2769</SRS>
+      <SRS>EPSG:2770</SRS>
+      <SRS>EPSG:2771</SRS>
+      <SRS>EPSG:2772</SRS>
+      <SRS>EPSG:2773</SRS>
+      <SRS>EPSG:2774</SRS>
+      <SRS>EPSG:2775</SRS>
+      <SRS>EPSG:2776</SRS>
+      <SRS>EPSG:2777</SRS>
+      <SRS>EPSG:2778</SRS>
+      <SRS>EPSG:2779</SRS>
+      <SRS>EPSG:2780</SRS>
+      <SRS>EPSG:2781</SRS>
+      <SRS>EPSG:2782</SRS>
+      <SRS>EPSG:2783</SRS>
+      <SRS>EPSG:2784</SRS>
+      <SRS>EPSG:2785</SRS>
+      <SRS>EPSG:2786</SRS>
+      <SRS>EPSG:2787</SRS>
+      <SRS>EPSG:2788</SRS>
+      <SRS>EPSG:2789</SRS>
+      <SRS>EPSG:2790</SRS>
+      <SRS>EPSG:2791</SRS>
+      <SRS>EPSG:2792</SRS>
+      <SRS>EPSG:2793</SRS>
+      <SRS>EPSG:2794</SRS>
+      <SRS>EPSG:2795</SRS>
+      <SRS>EPSG:2796</SRS>
+      <SRS>EPSG:2797</SRS>
+      <SRS>EPSG:2798</SRS>
+      <SRS>EPSG:2799</SRS>
+      <SRS>EPSG:2800</SRS>
+      <SRS>EPSG:2801</SRS>
+      <SRS>EPSG:2802</SRS>
+      <SRS>EPSG:2803</SRS>
+      <SRS>EPSG:2804</SRS>
+      <SRS>EPSG:2805</SRS>
+      <SRS>EPSG:2806</SRS>
+      <SRS>EPSG:2807</SRS>
+      <SRS>EPSG:2808</SRS>
+      <SRS>EPSG:2809</SRS>
+      <SRS>EPSG:2810</SRS>
+      <SRS>EPSG:2811</SRS>
+      <SRS>EPSG:2812</SRS>
+      <SRS>EPSG:2813</SRS>
+      <SRS>EPSG:2814</SRS>
+      <SRS>EPSG:2815</SRS>
+      <SRS>EPSG:2816</SRS>
+      <SRS>EPSG:2817</SRS>
+      <SRS>EPSG:2818</SRS>
+      <SRS>EPSG:2819</SRS>
+      <SRS>EPSG:2820</SRS>
+      <SRS>EPSG:2821</SRS>
+      <SRS>EPSG:2822</SRS>
+      <SRS>EPSG:2823</SRS>
+      <SRS>EPSG:2824</SRS>
+      <SRS>EPSG:2825</SRS>
+      <SRS>EPSG:2826</SRS>
+      <SRS>EPSG:2827</SRS>
+      <SRS>EPSG:2828</SRS>
+      <SRS>EPSG:2829</SRS>
+      <SRS>EPSG:2830</SRS>
+      <SRS>EPSG:2831</SRS>
+      <SRS>EPSG:2832</SRS>
+      <SRS>EPSG:2833</SRS>
+      <SRS>EPSG:2834</SRS>
+      <SRS>EPSG:2835</SRS>
+      <SRS>EPSG:2836</SRS>
+      <SRS>EPSG:2837</SRS>
+      <SRS>EPSG:2838</SRS>
+      <SRS>EPSG:2839</SRS>
+      <SRS>EPSG:2840</SRS>
+      <SRS>EPSG:2841</SRS>
+      <SRS>EPSG:2842</SRS>
+      <SRS>EPSG:2843</SRS>
+      <SRS>EPSG:2844</SRS>
+      <SRS>EPSG:2845</SRS>
+      <SRS>EPSG:2846</SRS>
+      <SRS>EPSG:2847</SRS>
+      <SRS>EPSG:2848</SRS>
+      <SRS>EPSG:2849</SRS>
+      <SRS>EPSG:2850</SRS>
+      <SRS>EPSG:2851</SRS>
+      <SRS>EPSG:2852</SRS>
+      <SRS>EPSG:2853</SRS>
+      <SRS>EPSG:2854</SRS>
+      <SRS>EPSG:2855</SRS>
+      <SRS>EPSG:2856</SRS>
+      <SRS>EPSG:2857</SRS>
+      <SRS>EPSG:2858</SRS>
+      <SRS>EPSG:2859</SRS>
+      <SRS>EPSG:2860</SRS>
+      <SRS>EPSG:2861</SRS>
+      <SRS>EPSG:2862</SRS>
+      <SRS>EPSG:2863</SRS>
+      <SRS>EPSG:2864</SRS>
+      <SRS>EPSG:2865</SRS>
+      <SRS>EPSG:2866</SRS>
+      <SRS>EPSG:2867</SRS>
+      <SRS>EPSG:2868</SRS>
+      <SRS>EPSG:2869</SRS>
+      <SRS>EPSG:2870</SRS>
+      <SRS>EPSG:2871</SRS>
+      <SRS>EPSG:2872</SRS>
+      <SRS>EPSG:2873</SRS>
+      <SRS>EPSG:2874</SRS>
+      <SRS>EPSG:2875</SRS>
+      <SRS>EPSG:2876</SRS>
+      <SRS>EPSG:2877</SRS>
+      <SRS>EPSG:2878</SRS>
+      <SRS>EPSG:2879</SRS>
+      <SRS>EPSG:2880</SRS>
+      <SRS>EPSG:2881</SRS>
+      <SRS>EPSG:2882</SRS>
+      <SRS>EPSG:2883</SRS>
+      <SRS>EPSG:2884</SRS>
+      <SRS>EPSG:2885</SRS>
+      <SRS>EPSG:2886</SRS>
+      <SRS>EPSG:2887</SRS>
+      <SRS>EPSG:2888</SRS>
+      <SRS>EPSG:2889</SRS>
+      <SRS>EPSG:2890</SRS>
+      <SRS>EPSG:2891</SRS>
+      <SRS>EPSG:2892</SRS>
+      <SRS>EPSG:2893</SRS>
+      <SRS>EPSG:2894</SRS>
+      <SRS>EPSG:2895</SRS>
+      <SRS>EPSG:2896</SRS>
+      <SRS>EPSG:2897</SRS>
+      <SRS>EPSG:2898</SRS>
+      <SRS>EPSG:2899</SRS>
+      <SRS>EPSG:2900</SRS>
+      <SRS>EPSG:2901</SRS>
+      <SRS>EPSG:2902</SRS>
+      <SRS>EPSG:2903</SRS>
+      <SRS>EPSG:2904</SRS>
+      <SRS>EPSG:2905</SRS>
+      <SRS>EPSG:2906</SRS>
+      <SRS>EPSG:2907</SRS>
+      <SRS>EPSG:2908</SRS>
+      <SRS>EPSG:2909</SRS>
+      <SRS>EPSG:2910</SRS>
+      <SRS>EPSG:2911</SRS>
+      <SRS>EPSG:2912</SRS>
+      <SRS>EPSG:2913</SRS>
+      <SRS>EPSG:2914</SRS>
+      <SRS>EPSG:2915</SRS>
+      <SRS>EPSG:2916</SRS>
+      <SRS>EPSG:2917</SRS>
+      <SRS>EPSG:2918</SRS>
+      <SRS>EPSG:2919</SRS>
+      <SRS>EPSG:2920</SRS>
+      <SRS>EPSG:2921</SRS>
+      <SRS>EPSG:2922</SRS>
+      <SRS>EPSG:2923</SRS>
+      <SRS>EPSG:2924</SRS>
+      <SRS>EPSG:2925</SRS>
+      <SRS>EPSG:2926</SRS>
+      <SRS>EPSG:2927</SRS>
+      <SRS>EPSG:2928</SRS>
+      <SRS>EPSG:2929</SRS>
+      <SRS>EPSG:2930</SRS>
+      <SRS>EPSG:2931</SRS>
+      <SRS>EPSG:2932</SRS>
+      <SRS>EPSG:2933</SRS>
+      <SRS>EPSG:2934</SRS>
+      <SRS>EPSG:2935</SRS>
+      <SRS>EPSG:2936</SRS>
+      <SRS>EPSG:2937</SRS>
+      <SRS>EPSG:2938</SRS>
+      <SRS>EPSG:2939</SRS>
+      <SRS>EPSG:2940</SRS>
+      <SRS>EPSG:2941</SRS>
+      <SRS>EPSG:2942</SRS>
+      <SRS>EPSG:2943</SRS>
+      <SRS>EPSG:2944</SRS>
+      <SRS>EPSG:2945</SRS>
+      <SRS>EPSG:2946</SRS>
+      <SRS>EPSG:2947</SRS>
+      <SRS>EPSG:2948</SRS>
+      <SRS>EPSG:2949</SRS>
+      <SRS>EPSG:2950</SRS>
+      <SRS>EPSG:2951</SRS>
+      <SRS>EPSG:2952</SRS>
+      <SRS>EPSG:2953</SRS>
+      <SRS>EPSG:2954</SRS>
+      <SRS>EPSG:2955</SRS>
+      <SRS>EPSG:2956</SRS>
+      <SRS>EPSG:2957</SRS>
+      <SRS>EPSG:2958</SRS>
+      <SRS>EPSG:2959</SRS>
+      <SRS>EPSG:2960</SRS>
+      <SRS>EPSG:2961</SRS>
+      <SRS>EPSG:2962</SRS>
+      <SRS>EPSG:2963</SRS>
+      <SRS>EPSG:2964</SRS>
+      <SRS>EPSG:2965</SRS>
+      <SRS>EPSG:2966</SRS>
+      <SRS>EPSG:2967</SRS>
+      <SRS>EPSG:2968</SRS>
+      <SRS>EPSG:2969</SRS>
+      <SRS>EPSG:2970</SRS>
+      <SRS>EPSG:2971</SRS>
+      <SRS>EPSG:2972</SRS>
+      <SRS>EPSG:2973</SRS>
+      <SRS>EPSG:2975</SRS>
+      <SRS>EPSG:2976</SRS>
+      <SRS>EPSG:2977</SRS>
+      <SRS>EPSG:2978</SRS>
+      <SRS>EPSG:2979</SRS>
+      <SRS>EPSG:2980</SRS>
+      <SRS>EPSG:2981</SRS>
+      <SRS>EPSG:2982</SRS>
+      <SRS>EPSG:2983</SRS>
+      <SRS>EPSG:2984</SRS>
+      <SRS>EPSG:2985</SRS>
+      <SRS>EPSG:2986</SRS>
+      <SRS>EPSG:2987</SRS>
+      <SRS>EPSG:2988</SRS>
+      <SRS>EPSG:2989</SRS>
+      <SRS>EPSG:2990</SRS>
+      <SRS>EPSG:2991</SRS>
+      <SRS>EPSG:2992</SRS>
+      <SRS>EPSG:2993</SRS>
+      <SRS>EPSG:2994</SRS>
+      <SRS>EPSG:2995</SRS>
+      <SRS>EPSG:2996</SRS>
+      <SRS>EPSG:2997</SRS>
+      <SRS>EPSG:2998</SRS>
+      <SRS>EPSG:2999</SRS>
+      <SRS>EPSG:3000</SRS>
+      <SRS>EPSG:3001</SRS>
+      <SRS>EPSG:3002</SRS>
+      <SRS>EPSG:3003</SRS>
+      <SRS>EPSG:3004</SRS>
+      <SRS>EPSG:3005</SRS>
+      <SRS>EPSG:3006</SRS>
+      <SRS>EPSG:3007</SRS>
+      <SRS>EPSG:3008</SRS>
+      <SRS>EPSG:3009</SRS>
+      <SRS>EPSG:3010</SRS>
+      <SRS>EPSG:3011</SRS>
+      <SRS>EPSG:3012</SRS>
+      <SRS>EPSG:3013</SRS>
+      <SRS>EPSG:3014</SRS>
+      <SRS>EPSG:3015</SRS>
+      <SRS>EPSG:3016</SRS>
+      <SRS>EPSG:3017</SRS>
+      <SRS>EPSG:3018</SRS>
+      <SRS>EPSG:3019</SRS>
+      <SRS>EPSG:3020</SRS>
+      <SRS>EPSG:3021</SRS>
+      <SRS>EPSG:3022</SRS>
+      <SRS>EPSG:3023</SRS>
+      <SRS>EPSG:3024</SRS>
+      <SRS>EPSG:3025</SRS>
+      <SRS>EPSG:3026</SRS>
+      <SRS>EPSG:3027</SRS>
+      <SRS>EPSG:3028</SRS>
+      <SRS>EPSG:3029</SRS>
+      <SRS>EPSG:3030</SRS>
+      <SRS>EPSG:3031</SRS>
+      <SRS>EPSG:3032</SRS>
+      <SRS>EPSG:3033</SRS>
+      <SRS>EPSG:3034</SRS>
+      <SRS>EPSG:3035</SRS>
+      <SRS>EPSG:3036</SRS>
+      <SRS>EPSG:3037</SRS>
+      <SRS>EPSG:3038</SRS>
+      <SRS>EPSG:3039</SRS>
+      <SRS>EPSG:3040</SRS>
+      <SRS>EPSG:3041</SRS>
+      <SRS>EPSG:3042</SRS>
+      <SRS>EPSG:3043</SRS>
+      <SRS>EPSG:3044</SRS>
+      <SRS>EPSG:3045</SRS>
+      <SRS>EPSG:3046</SRS>
+      <SRS>EPSG:3047</SRS>
+      <SRS>EPSG:3048</SRS>
+      <SRS>EPSG:3049</SRS>
+      <SRS>EPSG:3050</SRS>
+      <SRS>EPSG:3051</SRS>
+      <SRS>EPSG:3052</SRS>
+      <SRS>EPSG:3053</SRS>
+      <SRS>EPSG:3054</SRS>
+      <SRS>EPSG:3055</SRS>
+      <SRS>EPSG:3056</SRS>
+      <SRS>EPSG:3057</SRS>
+      <SRS>EPSG:3058</SRS>
+      <SRS>EPSG:3059</SRS>
+      <SRS>EPSG:3060</SRS>
+      <SRS>EPSG:3061</SRS>
+      <SRS>EPSG:3062</SRS>
+      <SRS>EPSG:3063</SRS>
+      <SRS>EPSG:3064</SRS>
+      <SRS>EPSG:3065</SRS>
+      <SRS>EPSG:3066</SRS>
+      <SRS>EPSG:3067</SRS>
+      <SRS>EPSG:3068</SRS>
+      <SRS>EPSG:3069</SRS>
+      <SRS>EPSG:3070</SRS>
+      <SRS>EPSG:3071</SRS>
+      <SRS>EPSG:3072</SRS>
+      <SRS>EPSG:3073</SRS>
+      <SRS>EPSG:3074</SRS>
+      <SRS>EPSG:3075</SRS>
+      <SRS>EPSG:3076</SRS>
+      <SRS>EPSG:3077</SRS>
+      <SRS>EPSG:3078</SRS>
+      <SRS>EPSG:3079</SRS>
+      <SRS>EPSG:3080</SRS>
+      <SRS>EPSG:3081</SRS>
+      <SRS>EPSG:3082</SRS>
+      <SRS>EPSG:3083</SRS>
+      <SRS>EPSG:3084</SRS>
+      <SRS>EPSG:3085</SRS>
+      <SRS>EPSG:3086</SRS>
+      <SRS>EPSG:3087</SRS>
+      <SRS>EPSG:3088</SRS>
+      <SRS>EPSG:3089</SRS>
+      <SRS>EPSG:3090</SRS>
+      <SRS>EPSG:3091</SRS>
+      <SRS>EPSG:3092</SRS>
+      <SRS>EPSG:3093</SRS>
+      <SRS>EPSG:3094</SRS>
+      <SRS>EPSG:3095</SRS>
+      <SRS>EPSG:3096</SRS>
+      <SRS>EPSG:3097</SRS>
+      <SRS>EPSG:3098</SRS>
+      <SRS>EPSG:3099</SRS>
+      <SRS>EPSG:3100</SRS>
+      <SRS>EPSG:3101</SRS>
+      <SRS>EPSG:3102</SRS>
+      <SRS>EPSG:3103</SRS>
+      <SRS>EPSG:3104</SRS>
+      <SRS>EPSG:3105</SRS>
+      <SRS>EPSG:3106</SRS>
+      <SRS>EPSG:3107</SRS>
+      <SRS>EPSG:3108</SRS>
+      <SRS>EPSG:3109</SRS>
+      <SRS>EPSG:3110</SRS>
+      <SRS>EPSG:3111</SRS>
+      <SRS>EPSG:3112</SRS>
+      <SRS>EPSG:3113</SRS>
+      <SRS>EPSG:3114</SRS>
+      <SRS>EPSG:3115</SRS>
+      <SRS>EPSG:3116</SRS>
+      <SRS>EPSG:3117</SRS>
+      <SRS>EPSG:3118</SRS>
+      <SRS>EPSG:3119</SRS>
+      <SRS>EPSG:3120</SRS>
+      <SRS>EPSG:3121</SRS>
+      <SRS>EPSG:3122</SRS>
+      <SRS>EPSG:3123</SRS>
+      <SRS>EPSG:3124</SRS>
+      <SRS>EPSG:3125</SRS>
+      <SRS>EPSG:3126</SRS>
+      <SRS>EPSG:3127</SRS>
+      <SRS>EPSG:3128</SRS>
+      <SRS>EPSG:3129</SRS>
+      <SRS>EPSG:3130</SRS>
+      <SRS>EPSG:3131</SRS>
+      <SRS>EPSG:3132</SRS>
+      <SRS>EPSG:3133</SRS>
+      <SRS>EPSG:3134</SRS>
+      <SRS>EPSG:3135</SRS>
+      <SRS>EPSG:3136</SRS>
+      <SRS>EPSG:3137</SRS>
+      <SRS>EPSG:3138</SRS>
+      <SRS>EPSG:3139</SRS>
+      <SRS>EPSG:3140</SRS>
+      <SRS>EPSG:3141</SRS>
+      <SRS>EPSG:3142</SRS>
+      <SRS>EPSG:3143</SRS>
+      <SRS>EPSG:3144</SRS>
+      <SRS>EPSG:3145</SRS>
+      <SRS>EPSG:3146</SRS>
+      <SRS>EPSG:3147</SRS>
+      <SRS>EPSG:3148</SRS>
+      <SRS>EPSG:3149</SRS>
+      <SRS>EPSG:3150</SRS>
+      <SRS>EPSG:3151</SRS>
+      <SRS>EPSG:3152</SRS>
+      <SRS>EPSG:3153</SRS>
+      <SRS>EPSG:3154</SRS>
+      <SRS>EPSG:3155</SRS>
+      <SRS>EPSG:3156</SRS>
+      <SRS>EPSG:3157</SRS>
+      <SRS>EPSG:3158</SRS>
+      <SRS>EPSG:3159</SRS>
+      <SRS>EPSG:3160</SRS>
+      <SRS>EPSG:3161</SRS>
+      <SRS>EPSG:3162</SRS>
+      <SRS>EPSG:3163</SRS>
+      <SRS>EPSG:3164</SRS>
+      <SRS>EPSG:3165</SRS>
+      <SRS>EPSG:3166</SRS>
+      <SRS>EPSG:3167</SRS>
+      <SRS>EPSG:3168</SRS>
+      <SRS>EPSG:3169</SRS>
+      <SRS>EPSG:3170</SRS>
+      <SRS>EPSG:3171</SRS>
+      <SRS>EPSG:3172</SRS>
+      <SRS>EPSG:3173</SRS>
+      <SRS>EPSG:3174</SRS>
+      <SRS>EPSG:3175</SRS>
+      <SRS>EPSG:3176</SRS>
+      <SRS>EPSG:3177</SRS>
+      <SRS>EPSG:3178</SRS>
+      <SRS>EPSG:3179</SRS>
+      <SRS>EPSG:3180</SRS>
+      <SRS>EPSG:3181</SRS>
+      <SRS>EPSG:3182</SRS>
+      <SRS>EPSG:3183</SRS>
+      <SRS>EPSG:3184</SRS>
+      <SRS>EPSG:3185</SRS>
+      <SRS>EPSG:3186</SRS>
+      <SRS>EPSG:3187</SRS>
+      <SRS>EPSG:3188</SRS>
+      <SRS>EPSG:3189</SRS>
+      <SRS>EPSG:3190</SRS>
+      <SRS>EPSG:3191</SRS>
+      <SRS>EPSG:3192</SRS>
+      <SRS>EPSG:3193</SRS>
+      <SRS>EPSG:3194</SRS>
+      <SRS>EPSG:3195</SRS>
+      <SRS>EPSG:3196</SRS>
+      <SRS>EPSG:3197</SRS>
+      <SRS>EPSG:3198</SRS>
+      <SRS>EPSG:3199</SRS>
+      <SRS>EPSG:3200</SRS>
+      <SRS>EPSG:3201</SRS>
+      <SRS>EPSG:3202</SRS>
+      <SRS>EPSG:3203</SRS>
+      <SRS>EPSG:3204</SRS>
+      <SRS>EPSG:3205</SRS>
+      <SRS>EPSG:3206</SRS>
+      <SRS>EPSG:3207</SRS>
+      <SRS>EPSG:3208</SRS>
+      <SRS>EPSG:3209</SRS>
+      <SRS>EPSG:3210</SRS>
+      <SRS>EPSG:3211</SRS>
+      <SRS>EPSG:3212</SRS>
+      <SRS>EPSG:3213</SRS>
+      <SRS>EPSG:3214</SRS>
+      <SRS>EPSG:3215</SRS>
+      <SRS>EPSG:3216</SRS>
+      <SRS>EPSG:3217</SRS>
+      <SRS>EPSG:3218</SRS>
+      <SRS>EPSG:3219</SRS>
+      <SRS>EPSG:3220</SRS>
+      <SRS>EPSG:3221</SRS>
+      <SRS>EPSG:3222</SRS>
+      <SRS>EPSG:3223</SRS>
+      <SRS>EPSG:3224</SRS>
+      <SRS>EPSG:3225</SRS>
+      <SRS>EPSG:3226</SRS>
+      <SRS>EPSG:3227</SRS>
+      <SRS>EPSG:3228</SRS>
+      <SRS>EPSG:3229</SRS>
+      <SRS>EPSG:3230</SRS>
+      <SRS>EPSG:3231</SRS>
+      <SRS>EPSG:3232</SRS>
+      <SRS>EPSG:3233</SRS>
+      <SRS>EPSG:3234</SRS>
+      <SRS>EPSG:3235</SRS>
+      <SRS>EPSG:3236</SRS>
+      <SRS>EPSG:3237</SRS>
+      <SRS>EPSG:3238</SRS>
+      <SRS>EPSG:3239</SRS>
+      <SRS>EPSG:3240</SRS>
+      <SRS>EPSG:3241</SRS>
+      <SRS>EPSG:3242</SRS>
+      <SRS>EPSG:3243</SRS>
+      <SRS>EPSG:3244</SRS>
+      <SRS>EPSG:3245</SRS>
+      <SRS>EPSG:3246</SRS>
+      <SRS>EPSG:3247</SRS>
+      <SRS>EPSG:3248</SRS>
+      <SRS>EPSG:3249</SRS>
+      <SRS>EPSG:3250</SRS>
+      <SRS>EPSG:3251</SRS>
+      <SRS>EPSG:3252</SRS>
+      <SRS>EPSG:3253</SRS>
+      <SRS>EPSG:3254</SRS>
+      <SRS>EPSG:3255</SRS>
+      <SRS>EPSG:3256</SRS>
+      <SRS>EPSG:3257</SRS>
+      <SRS>EPSG:3258</SRS>
+      <SRS>EPSG:3259</SRS>
+      <SRS>EPSG:3260</SRS>
+      <SRS>EPSG:3261</SRS>
+      <SRS>EPSG:3262</SRS>
+      <SRS>EPSG:3263</SRS>
+      <SRS>EPSG:3264</SRS>
+      <SRS>EPSG:3265</SRS>
+      <SRS>EPSG:3266</SRS>
+      <SRS>EPSG:3267</SRS>
+      <SRS>EPSG:3268</SRS>
+      <SRS>EPSG:3269</SRS>
+      <SRS>EPSG:3270</SRS>
+      <SRS>EPSG:3271</SRS>
+      <SRS>EPSG:3272</SRS>
+      <SRS>EPSG:3273</SRS>
+      <SRS>EPSG:3274</SRS>
+      <SRS>EPSG:3275</SRS>
+      <SRS>EPSG:3276</SRS>
+      <SRS>EPSG:3277</SRS>
+      <SRS>EPSG:3278</SRS>
+      <SRS>EPSG:3279</SRS>
+      <SRS>EPSG:3280</SRS>
+      <SRS>EPSG:3281</SRS>
+      <SRS>EPSG:3282</SRS>
+      <SRS>EPSG:3283</SRS>
+      <SRS>EPSG:3284</SRS>
+      <SRS>EPSG:3285</SRS>
+      <SRS>EPSG:3286</SRS>
+      <SRS>EPSG:3287</SRS>
+      <SRS>EPSG:3288</SRS>
+      <SRS>EPSG:3289</SRS>
+      <SRS>EPSG:3290</SRS>
+      <SRS>EPSG:3291</SRS>
+      <SRS>EPSG:3292</SRS>
+      <SRS>EPSG:3293</SRS>
+      <SRS>EPSG:3294</SRS>
+      <SRS>EPSG:3295</SRS>
+      <SRS>EPSG:3296</SRS>
+      <SRS>EPSG:3297</SRS>
+      <SRS>EPSG:3298</SRS>
+      <SRS>EPSG:3299</SRS>
+      <SRS>EPSG:3300</SRS>
+      <SRS>EPSG:3301</SRS>
+      <SRS>EPSG:3302</SRS>
+      <SRS>EPSG:3303</SRS>
+      <SRS>EPSG:3304</SRS>
+      <SRS>EPSG:3305</SRS>
+      <SRS>EPSG:3306</SRS>
+      <SRS>EPSG:3307</SRS>
+      <SRS>EPSG:3308</SRS>
+      <SRS>EPSG:3309</SRS>
+      <SRS>EPSG:3310</SRS>
+      <SRS>EPSG:3311</SRS>
+      <SRS>EPSG:3312</SRS>
+      <SRS>EPSG:3313</SRS>
+      <SRS>EPSG:3314</SRS>
+      <SRS>EPSG:3315</SRS>
+      <SRS>EPSG:3316</SRS>
+      <SRS>EPSG:3317</SRS>
+      <SRS>EPSG:3318</SRS>
+      <SRS>EPSG:3319</SRS>
+      <SRS>EPSG:3320</SRS>
+      <SRS>EPSG:3321</SRS>
+      <SRS>EPSG:3322</SRS>
+      <SRS>EPSG:3323</SRS>
+      <SRS>EPSG:3324</SRS>
+      <SRS>EPSG:3325</SRS>
+      <SRS>EPSG:3326</SRS>
+      <SRS>EPSG:3327</SRS>
+      <SRS>EPSG:3328</SRS>
+      <SRS>EPSG:3329</SRS>
+      <SRS>EPSG:3330</SRS>
+      <SRS>EPSG:3331</SRS>
+      <SRS>EPSG:3332</SRS>
+      <SRS>EPSG:3333</SRS>
+      <SRS>EPSG:3334</SRS>
+      <SRS>EPSG:3335</SRS>
+      <SRS>EPSG:3336</SRS>
+      <SRS>EPSG:3337</SRS>
+      <SRS>EPSG:3338</SRS>
+      <SRS>EPSG:3339</SRS>
+      <SRS>EPSG:3340</SRS>
+      <SRS>EPSG:3341</SRS>
+      <SRS>EPSG:3342</SRS>
+      <SRS>EPSG:3343</SRS>
+      <SRS>EPSG:3344</SRS>
+      <SRS>EPSG:3345</SRS>
+      <SRS>EPSG:3346</SRS>
+      <SRS>EPSG:3347</SRS>
+      <SRS>EPSG:3348</SRS>
+      <SRS>EPSG:3349</SRS>
+      <SRS>EPSG:3350</SRS>
+      <SRS>EPSG:3351</SRS>
+      <SRS>EPSG:3352</SRS>
+      <SRS>EPSG:3353</SRS>
+      <SRS>EPSG:3354</SRS>
+      <SRS>EPSG:3355</SRS>
+      <SRS>EPSG:3356</SRS>
+      <SRS>EPSG:3357</SRS>
+      <SRS>EPSG:3358</SRS>
+      <SRS>EPSG:3359</SRS>
+      <SRS>EPSG:3360</SRS>
+      <SRS>EPSG:3361</SRS>
+      <SRS>EPSG:3362</SRS>
+      <SRS>EPSG:3363</SRS>
+      <SRS>EPSG:3364</SRS>
+      <SRS>EPSG:3365</SRS>
+      <SRS>EPSG:3366</SRS>
+      <SRS>EPSG:3367</SRS>
+      <SRS>EPSG:3368</SRS>
+      <SRS>EPSG:3369</SRS>
+      <SRS>EPSG:3370</SRS>
+      <SRS>EPSG:3371</SRS>
+      <SRS>EPSG:3372</SRS>
+      <SRS>EPSG:3373</SRS>
+      <SRS>EPSG:3374</SRS>
+      <SRS>EPSG:3375</SRS>
+      <SRS>EPSG:3376</SRS>
+      <SRS>EPSG:3377</SRS>
+      <SRS>EPSG:3378</SRS>
+      <SRS>EPSG:3379</SRS>
+      <SRS>EPSG:3380</SRS>
+      <SRS>EPSG:3381</SRS>
+      <SRS>EPSG:3382</SRS>
+      <SRS>EPSG:3383</SRS>
+      <SRS>EPSG:3384</SRS>
+      <SRS>EPSG:3385</SRS>
+      <SRS>EPSG:3386</SRS>
+      <SRS>EPSG:3387</SRS>
+      <SRS>EPSG:3388</SRS>
+      <SRS>EPSG:3389</SRS>
+      <SRS>EPSG:3390</SRS>
+      <SRS>EPSG:3391</SRS>
+      <SRS>EPSG:3392</SRS>
+      <SRS>EPSG:3393</SRS>
+      <SRS>EPSG:3394</SRS>
+      <SRS>EPSG:3395</SRS>
+      <SRS>EPSG:3396</SRS>
+      <SRS>EPSG:3397</SRS>
+      <SRS>EPSG:3398</SRS>
+      <SRS>EPSG:3399</SRS>
+      <SRS>EPSG:3400</SRS>
+      <SRS>EPSG:3401</SRS>
+      <SRS>EPSG:3402</SRS>
+      <SRS>EPSG:3403</SRS>
+      <SRS>EPSG:3404</SRS>
+      <SRS>EPSG:3405</SRS>
+      <SRS>EPSG:3406</SRS>
+      <SRS>EPSG:3407</SRS>
+      <SRS>EPSG:3408</SRS>
+      <SRS>EPSG:3409</SRS>
+      <SRS>EPSG:3410</SRS>
+      <SRS>EPSG:3411</SRS>
+      <SRS>EPSG:3412</SRS>
+      <SRS>EPSG:3413</SRS>
+      <SRS>EPSG:3414</SRS>
+      <SRS>EPSG:3415</SRS>
+      <SRS>EPSG:3416</SRS>
+      <SRS>EPSG:3417</SRS>
+      <SRS>EPSG:3418</SRS>
+      <SRS>EPSG:3419</SRS>
+      <SRS>EPSG:3420</SRS>
+      <SRS>EPSG:3421</SRS>
+      <SRS>EPSG:3422</SRS>
+      <SRS>EPSG:3423</SRS>
+      <SRS>EPSG:3424</SRS>
+      <SRS>EPSG:3425</SRS>
+      <SRS>EPSG:3426</SRS>
+      <SRS>EPSG:3427</SRS>
+      <SRS>EPSG:3428</SRS>
+      <SRS>EPSG:3429</SRS>
+      <SRS>EPSG:3430</SRS>
+      <SRS>EPSG:3431</SRS>
+      <SRS>EPSG:3432</SRS>
+      <SRS>EPSG:3433</SRS>
+      <SRS>EPSG:3434</SRS>
+      <SRS>EPSG:3435</SRS>
+      <SRS>EPSG:3436</SRS>
+      <SRS>EPSG:3437</SRS>
+      <SRS>EPSG:3438</SRS>
+      <SRS>EPSG:3439</SRS>
+      <SRS>EPSG:3440</SRS>
+      <SRS>EPSG:3441</SRS>
+      <SRS>EPSG:3442</SRS>
+      <SRS>EPSG:3443</SRS>
+      <SRS>EPSG:3444</SRS>
+      <SRS>EPSG:3445</SRS>
+      <SRS>EPSG:3446</SRS>
+      <SRS>EPSG:3447</SRS>
+      <SRS>EPSG:3448</SRS>
+      <SRS>EPSG:3449</SRS>
+      <SRS>EPSG:3450</SRS>
+      <SRS>EPSG:3451</SRS>
+      <SRS>EPSG:3452</SRS>
+      <SRS>EPSG:3453</SRS>
+      <SRS>EPSG:3454</SRS>
+      <SRS>EPSG:3455</SRS>
+      <SRS>EPSG:3456</SRS>
+      <SRS>EPSG:3457</SRS>
+      <SRS>EPSG:3458</SRS>
+      <SRS>EPSG:3459</SRS>
+      <SRS>EPSG:3460</SRS>
+      <SRS>EPSG:3461</SRS>
+      <SRS>EPSG:3462</SRS>
+      <SRS>EPSG:3463</SRS>
+      <SRS>EPSG:3464</SRS>
+      <SRS>EPSG:3560</SRS>
+      <SRS>EPSG:3561</SRS>
+      <SRS>EPSG:3562</SRS>
+      <SRS>EPSG:3563</SRS>
+      <SRS>EPSG:3564</SRS>
+      <SRS>EPSG:3565</SRS>
+      <SRS>EPSG:3566</SRS>
+      <SRS>EPSG:3567</SRS>
+      <SRS>EPSG:3568</SRS>
+      <SRS>EPSG:3569</SRS>
+      <SRS>EPSG:3570</SRS>
+      <SRS>EPSG:3571</SRS>
+      <SRS>EPSG:3572</SRS>
+      <SRS>EPSG:3573</SRS>
+      <SRS>EPSG:3574</SRS>
+      <SRS>EPSG:3575</SRS>
+      <SRS>EPSG:3576</SRS>
+      <SRS>EPSG:3577</SRS>
+      <SRS>EPSG:3920</SRS>
+      <SRS>EPSG:3991</SRS>
+      <SRS>EPSG:3992</SRS>
+      <SRS>EPSG:3993</SRS>
+      <SRS>EPSG:4001</SRS>
+      <SRS>EPSG:4002</SRS>
+      <SRS>EPSG:4003</SRS>
+      <SRS>EPSG:4004</SRS>
+      <SRS>EPSG:4005</SRS>
+      <SRS>EPSG:4006</SRS>
+      <SRS>EPSG:4007</SRS>
+      <SRS>EPSG:4008</SRS>
+      <SRS>EPSG:4009</SRS>
+      <SRS>EPSG:4010</SRS>
+      <SRS>EPSG:4011</SRS>
+      <SRS>EPSG:4012</SRS>
+      <SRS>EPSG:4013</SRS>
+      <SRS>EPSG:4014</SRS>
+      <SRS>EPSG:4015</SRS>
+      <SRS>EPSG:4016</SRS>
+      <SRS>EPSG:4018</SRS>
+      <SRS>EPSG:4019</SRS>
+      <SRS>EPSG:4020</SRS>
+      <SRS>EPSG:4021</SRS>
+      <SRS>EPSG:4022</SRS>
+      <SRS>EPSG:4024</SRS>
+      <SRS>EPSG:4025</SRS>
+      <SRS>EPSG:4027</SRS>
+      <SRS>EPSG:4028</SRS>
+      <SRS>EPSG:4029</SRS>
+      <SRS>EPSG:4030</SRS>
+      <SRS>EPSG:4031</SRS>
+      <SRS>EPSG:4032</SRS>
+      <SRS>EPSG:4033</SRS>
+      <SRS>EPSG:4034</SRS>
+      <SRS>EPSG:4035</SRS>
+      <SRS>EPSG:4036</SRS>
+      <SRS>EPSG:4041</SRS>
+      <SRS>EPSG:4042</SRS>
+      <SRS>EPSG:4043</SRS>
+      <SRS>EPSG:4044</SRS>
+      <SRS>EPSG:4045</SRS>
+      <SRS>EPSG:4047</SRS>
+      <SRS>EPSG:4052</SRS>
+      <SRS>EPSG:4053</SRS>
+      <SRS>EPSG:4054</SRS>
+      <SRS>EPSG:4120</SRS>
+      <SRS>EPSG:4121</SRS>
+      <SRS>EPSG:4122</SRS>
+      <SRS>EPSG:4123</SRS>
+      <SRS>EPSG:4124</SRS>
+      <SRS>EPSG:4125</SRS>
+      <SRS>EPSG:4126</SRS>
+      <SRS>EPSG:4127</SRS>
+      <SRS>EPSG:4128</SRS>
+      <SRS>EPSG:4129</SRS>
+      <SRS>EPSG:4130</SRS>
+      <SRS>EPSG:4131</SRS>
+      <SRS>EPSG:4132</SRS>
+      <SRS>EPSG:4133</SRS>
+      <SRS>EPSG:4134</SRS>
+      <SRS>EPSG:4135</SRS>
+      <SRS>EPSG:4136</SRS>
+      <SRS>EPSG:4137</SRS>
+      <SRS>EPSG:4138</SRS>
+      <SRS>EPSG:4139</SRS>
+      <SRS>EPSG:4140</SRS>
+      <SRS>EPSG:4141</SRS>
+      <SRS>EPSG:4142</SRS>
+      <SRS>EPSG:4143</SRS>
+      <SRS>EPSG:4144</SRS>
+      <SRS>EPSG:4145</SRS>
+      <SRS>EPSG:4146</SRS>
+      <SRS>EPSG:4147</SRS>
+      <SRS>EPSG:4148</SRS>
+      <SRS>EPSG:4149</SRS>
+      <SRS>EPSG:4150</SRS>
+      <SRS>EPSG:4151</SRS>
+      <SRS>EPSG:4152</SRS>
+      <SRS>EPSG:4153</SRS>
+      <SRS>EPSG:4154</SRS>
+      <SRS>EPSG:4155</SRS>
+      <SRS>EPSG:4156</SRS>
+      <SRS>EPSG:4157</SRS>
+      <SRS>EPSG:4158</SRS>
+      <SRS>EPSG:4159</SRS>
+      <SRS>EPSG:4160</SRS>
+      <SRS>EPSG:4161</SRS>
+      <SRS>EPSG:4162</SRS>
+      <SRS>EPSG:4163</SRS>
+      <SRS>EPSG:4164</SRS>
+      <SRS>EPSG:4165</SRS>
+      <SRS>EPSG:4166</SRS>
+      <SRS>EPSG:4167</SRS>
+      <SRS>EPSG:4168</SRS>
+      <SRS>EPSG:4169</SRS>
+      <SRS>EPSG:4170</SRS>
+      <SRS>EPSG:4171</SRS>
+      <SRS>EPSG:4172</SRS>
+      <SRS>EPSG:4173</SRS>
+      <SRS>EPSG:4174</SRS>
+      <SRS>EPSG:4175</SRS>
+      <SRS>EPSG:4176</SRS>
+      <SRS>EPSG:4178</SRS>
+      <SRS>EPSG:4179</SRS>
+      <SRS>EPSG:4180</SRS>
+      <SRS>EPSG:4181</SRS>
+      <SRS>EPSG:4182</SRS>
+      <SRS>EPSG:4183</SRS>
+      <SRS>EPSG:4184</SRS>
+      <SRS>EPSG:4185</SRS>
+      <SRS>EPSG:4188</SRS>
+      <SRS>EPSG:4189</SRS>
+      <SRS>EPSG:4190</SRS>
+      <SRS>EPSG:4191</SRS>
+      <SRS>EPSG:4192</SRS>
+      <SRS>EPSG:4193</SRS>
+      <SRS>EPSG:4194</SRS>
+      <SRS>EPSG:4195</SRS>
+      <SRS>EPSG:4196</SRS>
+      <SRS>EPSG:4197</SRS>
+      <SRS>EPSG:4198</SRS>
+      <SRS>EPSG:4199</SRS>
+      <SRS>EPSG:4200</SRS>
+      <SRS>EPSG:4201</SRS>
+      <SRS>EPSG:4202</SRS>
+      <SRS>EPSG:4203</SRS>
+      <SRS>EPSG:4204</SRS>
+      <SRS>EPSG:4205</SRS>
+      <SRS>EPSG:4206</SRS>
+      <SRS>EPSG:4207</SRS>
+      <SRS>EPSG:4208</SRS>
+      <SRS>EPSG:4209</SRS>
+      <SRS>EPSG:4210</SRS>
+      <SRS>EPSG:4211</SRS>
+      <SRS>EPSG:4212</SRS>
+      <SRS>EPSG:4213</SRS>
+      <SRS>EPSG:4214</SRS>
+      <SRS>EPSG:4215</SRS>
+      <SRS>EPSG:4216</SRS>
+      <SRS>EPSG:4218</SRS>
+      <SRS>EPSG:4219</SRS>
+      <SRS>EPSG:4220</SRS>
+      <SRS>EPSG:4221</SRS>
+      <SRS>EPSG:4222</SRS>
+      <SRS>EPSG:4223</SRS>
+      <SRS>EPSG:4224</SRS>
+      <SRS>EPSG:4225</SRS>
+      <SRS>EPSG:4226</SRS>
+      <SRS>EPSG:4227</SRS>
+      <SRS>EPSG:4228</SRS>
+      <SRS>EPSG:4229</SRS>
+      <SRS>EPSG:4230</SRS>
+      <SRS>EPSG:4231</SRS>
+      <SRS>EPSG:4232</SRS>
+      <SRS>EPSG:4233</SRS>
+      <SRS>EPSG:4234</SRS>
+      <SRS>EPSG:4235</SRS>
+      <SRS>EPSG:4236</SRS>
+      <SRS>EPSG:4237</SRS>
+      <SRS>EPSG:4238</SRS>
+      <SRS>EPSG:4239</SRS>
+      <SRS>EPSG:4240</SRS>
+      <SRS>EPSG:4241</SRS>
+      <SRS>EPSG:4242</SRS>
+      <SRS>EPSG:4243</SRS>
+      <SRS>EPSG:4244</SRS>
+      <SRS>EPSG:4245</SRS>
+      <SRS>EPSG:4246</SRS>
+      <SRS>EPSG:4247</SRS>
+      <SRS>EPSG:4248</SRS>
+      <SRS>EPSG:4249</SRS>
+      <SRS>EPSG:4250</SRS>
+      <SRS>EPSG:4251</SRS>
+      <SRS>EPSG:4252</SRS>
+      <SRS>EPSG:4253</SRS>
+      <SRS>EPSG:4254</SRS>
+      <SRS>EPSG:4255</SRS>
+      <SRS>EPSG:4256</SRS>
+      <SRS>EPSG:4257</SRS>
+      <SRS>EPSG:4258</SRS>
+      <SRS>EPSG:4259</SRS>
+      <SRS>EPSG:4260</SRS>
+      <SRS>EPSG:4261</SRS>
+      <SRS>EPSG:4262</SRS>
+      <SRS>EPSG:4263</SRS>
+      <SRS>EPSG:4264</SRS>
+      <SRS>EPSG:4265</SRS>
+      <SRS>EPSG:4266</SRS>
+      <SRS>EPSG:4267</SRS>
+      <SRS>EPSG:4268</SRS>
+      <SRS>EPSG:4269</SRS>
+      <SRS>EPSG:4270</SRS>
+      <SRS>EPSG:4271</SRS>
+      <SRS>EPSG:4272</SRS>
+      <SRS>EPSG:4273</SRS>
+      <SRS>EPSG:4274</SRS>
+      <SRS>EPSG:4275</SRS>
+      <SRS>EPSG:4276</SRS>
+      <SRS>EPSG:4277</SRS>
+      <SRS>EPSG:4278</SRS>
+      <SRS>EPSG:4279</SRS>
+      <SRS>EPSG:4280</SRS>
+      <SRS>EPSG:4281</SRS>
+      <SRS>EPSG:4282</SRS>
+      <SRS>EPSG:4283</SRS>
+      <SRS>EPSG:4284</SRS>
+      <SRS>EPSG:4285</SRS>
+      <SRS>EPSG:4286</SRS>
+      <SRS>EPSG:4287</SRS>
+      <SRS>EPSG:4288</SRS>
+      <SRS>EPSG:4289</SRS>
+      <SRS>EPSG:4291</SRS>
+      <SRS>EPSG:4292</SRS>
+      <SRS>EPSG:4293</SRS>
+      <SRS>EPSG:4294</SRS>
+      <SRS>EPSG:4295</SRS>
+      <SRS>EPSG:4296</SRS>
+      <SRS>EPSG:4297</SRS>
+      <SRS>EPSG:4298</SRS>
+      <SRS>EPSG:4299</SRS>
+      <SRS>EPSG:4300</SRS>
+      <SRS>EPSG:4301</SRS>
+      <SRS>EPSG:4302</SRS>
+      <SRS>EPSG:4303</SRS>
+      <SRS>EPSG:4304</SRS>
+      <SRS>EPSG:4306</SRS>
+      <SRS>EPSG:4307</SRS>
+      <SRS>EPSG:4308</SRS>
+      <SRS>EPSG:4309</SRS>
+      <SRS>EPSG:4310</SRS>
+      <SRS>EPSG:4311</SRS>
+      <SRS>EPSG:4312</SRS>
+      <SRS>EPSG:4313</SRS>
+      <SRS>EPSG:4314</SRS>
+      <SRS>EPSG:4315</SRS>
+      <SRS>EPSG:4316</SRS>
+      <SRS>EPSG:4317</SRS>
+      <SRS>EPSG:4318</SRS>
+      <SRS>EPSG:4319</SRS>
+      <SRS>EPSG:4322</SRS>
+      <SRS>EPSG:4324</SRS>
+      <SRS>EPSG:4326</SRS>
+      <SRS>EPSG:4327</SRS>
+      <SRS>EPSG:4328</SRS>
+      <SRS>EPSG:4329</SRS>
+      <SRS>EPSG:4330</SRS>
+      <SRS>EPSG:4331</SRS>
+      <SRS>EPSG:4332</SRS>
+      <SRS>EPSG:4333</SRS>
+      <SRS>EPSG:4334</SRS>
+      <SRS>EPSG:4335</SRS>
+      <SRS>EPSG:4336</SRS>
+      <SRS>EPSG:4337</SRS>
+      <SRS>EPSG:4338</SRS>
+      <SRS>EPSG:4339</SRS>
+      <SRS>EPSG:4340</SRS>
+      <SRS>EPSG:4341</SRS>
+      <SRS>EPSG:4342</SRS>
+      <SRS>EPSG:4343</SRS>
+      <SRS>EPSG:4344</SRS>
+      <SRS>EPSG:4345</SRS>
+      <SRS>EPSG:4346</SRS>
+      <SRS>EPSG:4347</SRS>
+      <SRS>EPSG:4348</SRS>
+      <SRS>EPSG:4349</SRS>
+      <SRS>EPSG:4350</SRS>
+      <SRS>EPSG:4351</SRS>
+      <SRS>EPSG:4352</SRS>
+      <SRS>EPSG:4353</SRS>
+      <SRS>EPSG:4354</SRS>
+      <SRS>EPSG:4355</SRS>
+      <SRS>EPSG:4356</SRS>
+      <SRS>EPSG:4357</SRS>
+      <SRS>EPSG:4358</SRS>
+      <SRS>EPSG:4359</SRS>
+      <SRS>EPSG:4360</SRS>
+      <SRS>EPSG:4361</SRS>
+      <SRS>EPSG:4362</SRS>
+      <SRS>EPSG:4363</SRS>
+      <SRS>EPSG:4364</SRS>
+      <SRS>EPSG:4365</SRS>
+      <SRS>EPSG:4366</SRS>
+      <SRS>EPSG:4367</SRS>
+      <SRS>EPSG:4368</SRS>
+      <SRS>EPSG:4369</SRS>
+      <SRS>EPSG:4370</SRS>
+      <SRS>EPSG:4371</SRS>
+      <SRS>EPSG:4372</SRS>
+      <SRS>EPSG:4373</SRS>
+      <SRS>EPSG:4374</SRS>
+      <SRS>EPSG:4375</SRS>
+      <SRS>EPSG:4376</SRS>
+      <SRS>EPSG:4377</SRS>
+      <SRS>EPSG:4378</SRS>
+      <SRS>EPSG:4379</SRS>
+      <SRS>EPSG:4380</SRS>
+      <SRS>EPSG:4381</SRS>
+      <SRS>EPSG:4382</SRS>
+      <SRS>EPSG:4383</SRS>
+      <SRS>EPSG:4384</SRS>
+      <SRS>EPSG:4385</SRS>
+      <SRS>EPSG:4386</SRS>
+      <SRS>EPSG:4387</SRS>
+      <SRS>EPSG:4388</SRS>
+      <SRS>EPSG:4389</SRS>
+      <SRS>EPSG:4600</SRS>
+      <SRS>EPSG:4601</SRS>
+      <SRS>EPSG:4602</SRS>
+      <SRS>EPSG:4603</SRS>
+      <SRS>EPSG:4604</SRS>
+      <SRS>EPSG:4605</SRS>
+      <SRS>EPSG:4606</SRS>
+      <SRS>EPSG:4607</SRS>
+      <SRS>EPSG:4608</SRS>
+      <SRS>EPSG:4609</SRS>
+      <SRS>EPSG:4610</SRS>
+      <SRS>EPSG:4611</SRS>
+      <SRS>EPSG:4612</SRS>
+      <SRS>EPSG:4613</SRS>
+      <SRS>EPSG:4614</SRS>
+      <SRS>EPSG:4615</SRS>
+      <SRS>EPSG:4616</SRS>
+      <SRS>EPSG:4617</SRS>
+      <SRS>EPSG:4618</SRS>
+      <SRS>EPSG:4619</SRS>
+      <SRS>EPSG:4620</SRS>
+      <SRS>EPSG:4621</SRS>
+      <SRS>EPSG:4622</SRS>
+      <SRS>EPSG:4623</SRS>
+      <SRS>EPSG:4624</SRS>
+      <SRS>EPSG:4625</SRS>
+      <SRS>EPSG:4626</SRS>
+      <SRS>EPSG:4627</SRS>
+      <SRS>EPSG:4628</SRS>
+      <SRS>EPSG:4629</SRS>
+      <SRS>EPSG:4630</SRS>
+      <SRS>EPSG:4631</SRS>
+      <SRS>EPSG:4632</SRS>
+      <SRS>EPSG:4633</SRS>
+      <SRS>EPSG:4634</SRS>
+      <SRS>EPSG:4635</SRS>
+      <SRS>EPSG:4636</SRS>
+      <SRS>EPSG:4637</SRS>
+      <SRS>EPSG:4638</SRS>
+      <SRS>EPSG:4639</SRS>
+      <SRS>EPSG:4640</SRS>
+      <SRS>EPSG:4641</SRS>
+      <SRS>EPSG:4642</SRS>
+      <SRS>EPSG:4643</SRS>
+      <SRS>EPSG:4644</SRS>
+      <SRS>EPSG:4645</SRS>
+      <SRS>EPSG:4646</SRS>
+      <SRS>EPSG:4657</SRS>
+      <SRS>EPSG:4658</SRS>
+      <SRS>EPSG:4659</SRS>
+      <SRS>EPSG:4660</SRS>
+      <SRS>EPSG:4661</SRS>
+      <SRS>EPSG:4662</SRS>
+      <SRS>EPSG:4663</SRS>
+      <SRS>EPSG:4664</SRS>
+      <SRS>EPSG:4665</SRS>
+      <SRS>EPSG:4666</SRS>
+      <SRS>EPSG:4667</SRS>
+      <SRS>EPSG:4668</SRS>
+      <SRS>EPSG:4669</SRS>
+      <SRS>EPSG:4670</SRS>
+      <SRS>EPSG:4671</SRS>
+      <SRS>EPSG:4672</SRS>
+      <SRS>EPSG:4673</SRS>
+      <SRS>EPSG:4674</SRS>
+      <SRS>EPSG:4675</SRS>
+      <SRS>EPSG:4676</SRS>
+      <SRS>EPSG:4677</SRS>
+      <SRS>EPSG:4678</SRS>
+      <SRS>EPSG:4679</SRS>
+      <SRS>EPSG:4680</SRS>
+      <SRS>EPSG:4681</SRS>
+      <SRS>EPSG:4682</SRS>
+      <SRS>EPSG:4683</SRS>
+      <SRS>EPSG:4684</SRS>
+      <SRS>EPSG:4685</SRS>
+      <SRS>EPSG:4686</SRS>
+      <SRS>EPSG:4687</SRS>
+      <SRS>EPSG:4688</SRS>
+      <SRS>EPSG:4689</SRS>
+      <SRS>EPSG:4690</SRS>
+      <SRS>EPSG:4691</SRS>
+      <SRS>EPSG:4692</SRS>
+      <SRS>EPSG:4693</SRS>
+      <SRS>EPSG:4694</SRS>
+      <SRS>EPSG:4695</SRS>
+      <SRS>EPSG:4696</SRS>
+      <SRS>EPSG:4697</SRS>
+      <SRS>EPSG:4698</SRS>
+      <SRS>EPSG:4699</SRS>
+      <SRS>EPSG:4700</SRS>
+      <SRS>EPSG:4701</SRS>
+      <SRS>EPSG:4702</SRS>
+      <SRS>EPSG:4703</SRS>
+      <SRS>EPSG:4704</SRS>
+      <SRS>EPSG:4705</SRS>
+      <SRS>EPSG:4706</SRS>
+      <SRS>EPSG:4707</SRS>
+      <SRS>EPSG:4708</SRS>
+      <SRS>EPSG:4709</SRS>
+      <SRS>EPSG:4710</SRS>
+      <SRS>EPSG:4711</SRS>
+      <SRS>EPSG:4712</SRS>
+      <SRS>EPSG:4713</SRS>
+      <SRS>EPSG:4714</SRS>
+      <SRS>EPSG:4715</SRS>
+      <SRS>EPSG:4716</SRS>
+      <SRS>EPSG:4717</SRS>
+      <SRS>EPSG:4718</SRS>
+      <SRS>EPSG:4719</SRS>
+      <SRS>EPSG:4720</SRS>
+      <SRS>EPSG:4721</SRS>
+      <SRS>EPSG:4722</SRS>
+      <SRS>EPSG:4723</SRS>
+      <SRS>EPSG:4724</SRS>
+      <SRS>EPSG:4725</SRS>
+      <SRS>EPSG:4726</SRS>
+      <SRS>EPSG:4727</SRS>
+      <SRS>EPSG:4728</SRS>
+      <SRS>EPSG:4729</SRS>
+      <SRS>EPSG:4730</SRS>
+      <SRS>EPSG:4731</SRS>
+      <SRS>EPSG:4732</SRS>
+      <SRS>EPSG:4733</SRS>
+      <SRS>EPSG:4734</SRS>
+      <SRS>EPSG:4735</SRS>
+      <SRS>EPSG:4736</SRS>
+      <SRS>EPSG:4737</SRS>
+      <SRS>EPSG:4738</SRS>
+      <SRS>EPSG:4739</SRS>
+      <SRS>EPSG:4740</SRS>
+      <SRS>EPSG:4741</SRS>
+      <SRS>EPSG:4742</SRS>
+      <SRS>EPSG:4743</SRS>
+      <SRS>EPSG:4744</SRS>
+      <SRS>EPSG:4745</SRS>
+      <SRS>EPSG:4746</SRS>
+      <SRS>EPSG:4747</SRS>
+      <SRS>EPSG:4748</SRS>
+      <SRS>EPSG:4749</SRS>
+      <SRS>EPSG:4750</SRS>
+      <SRS>EPSG:4751</SRS>
+      <SRS>EPSG:4752</SRS>
+      <SRS>EPSG:4753</SRS>
+      <SRS>EPSG:4754</SRS>
+      <SRS>EPSG:4755</SRS>
+      <SRS>EPSG:4756</SRS>
+      <SRS>EPSG:4757</SRS>
+      <SRS>EPSG:4758</SRS>
+      <SRS>EPSG:4801</SRS>
+      <SRS>EPSG:4802</SRS>
+      <SRS>EPSG:4803</SRS>
+      <SRS>EPSG:4804</SRS>
+      <SRS>EPSG:4805</SRS>
+      <SRS>EPSG:4806</SRS>
+      <SRS>EPSG:4807</SRS>
+      <SRS>EPSG:4808</SRS>
+      <SRS>EPSG:4809</SRS>
+      <SRS>EPSG:4810</SRS>
+      <SRS>EPSG:4811</SRS>
+      <SRS>EPSG:4813</SRS>
+      <SRS>EPSG:4814</SRS>
+      <SRS>EPSG:4815</SRS>
+      <SRS>EPSG:4816</SRS>
+      <SRS>EPSG:4817</SRS>
+      <SRS>EPSG:4818</SRS>
+      <SRS>EPSG:4819</SRS>
+      <SRS>EPSG:4820</SRS>
+      <SRS>EPSG:4821</SRS>
+      <SRS>EPSG:4894</SRS>
+      <SRS>EPSG:4895</SRS>
+      <SRS>EPSG:4896</SRS>
+      <SRS>EPSG:4897</SRS>
+      <SRS>EPSG:4898</SRS>
+      <SRS>EPSG:4899</SRS>
+      <SRS>EPSG:4900</SRS>
+      <SRS>EPSG:4901</SRS>
+      <SRS>EPSG:4902</SRS>
+      <SRS>EPSG:4903</SRS>
+      <SRS>EPSG:4904</SRS>
+      <SRS>EPSG:4906</SRS>
+      <SRS>EPSG:4907</SRS>
+      <SRS>EPSG:4908</SRS>
+      <SRS>EPSG:4909</SRS>
+      <SRS>EPSG:4910</SRS>
+      <SRS>EPSG:4911</SRS>
+      <SRS>EPSG:4912</SRS>
+      <SRS>EPSG:4913</SRS>
+      <SRS>EPSG:4914</SRS>
+      <SRS>EPSG:4915</SRS>
+      <SRS>EPSG:4916</SRS>
+      <SRS>EPSG:4917</SRS>
+      <SRS>EPSG:4918</SRS>
+      <SRS>EPSG:4919</SRS>
+      <SRS>EPSG:4920</SRS>
+      <SRS>EPSG:4921</SRS>
+      <SRS>EPSG:4922</SRS>
+      <SRS>EPSG:4923</SRS>
+      <SRS>EPSG:4924</SRS>
+      <SRS>EPSG:4925</SRS>
+      <SRS>EPSG:4926</SRS>
+      <SRS>EPSG:4927</SRS>
+      <SRS>EPSG:4928</SRS>
+      <SRS>EPSG:4929</SRS>
+      <SRS>EPSG:4930</SRS>
+      <SRS>EPSG:4931</SRS>
+      <SRS>EPSG:4932</SRS>
+      <SRS>EPSG:4933</SRS>
+      <SRS>EPSG:4934</SRS>
+      <SRS>EPSG:4935</SRS>
+      <SRS>EPSG:4936</SRS>
+      <SRS>EPSG:4937</SRS>
+      <SRS>EPSG:4938</SRS>
+      <SRS>EPSG:4939</SRS>
+      <SRS>EPSG:4940</SRS>
+      <SRS>EPSG:4941</SRS>
+      <SRS>EPSG:4942</SRS>
+      <SRS>EPSG:4943</SRS>
+      <SRS>EPSG:4944</SRS>
+      <SRS>EPSG:4945</SRS>
+      <SRS>EPSG:4946</SRS>
+      <SRS>EPSG:4947</SRS>
+      <SRS>EPSG:4948</SRS>
+      <SRS>EPSG:4949</SRS>
+      <SRS>EPSG:4950</SRS>
+      <SRS>EPSG:4951</SRS>
+      <SRS>EPSG:4952</SRS>
+      <SRS>EPSG:4953</SRS>
+      <SRS>EPSG:4954</SRS>
+      <SRS>EPSG:4955</SRS>
+      <SRS>EPSG:4956</SRS>
+      <SRS>EPSG:4957</SRS>
+      <SRS>EPSG:4958</SRS>
+      <SRS>EPSG:4959</SRS>
+      <SRS>EPSG:4960</SRS>
+      <SRS>EPSG:4961</SRS>
+      <SRS>EPSG:4962</SRS>
+      <SRS>EPSG:4963</SRS>
+      <SRS>EPSG:4964</SRS>
+      <SRS>EPSG:4965</SRS>
+      <SRS>EPSG:4966</SRS>
+      <SRS>EPSG:4967</SRS>
+      <SRS>EPSG:4968</SRS>
+      <SRS>EPSG:4969</SRS>
+      <SRS>EPSG:4970</SRS>
+      <SRS>EPSG:4971</SRS>
+      <SRS>EPSG:4972</SRS>
+      <SRS>EPSG:4973</SRS>
+      <SRS>EPSG:4974</SRS>
+      <SRS>EPSG:4975</SRS>
+      <SRS>EPSG:4976</SRS>
+      <SRS>EPSG:4977</SRS>
+      <SRS>EPSG:4978</SRS>
+      <SRS>EPSG:4979</SRS>
+      <SRS>EPSG:4980</SRS>
+      <SRS>EPSG:4981</SRS>
+      <SRS>EPSG:4982</SRS>
+      <SRS>EPSG:4983</SRS>
+      <SRS>EPSG:4984</SRS>
+      <SRS>EPSG:4985</SRS>
+      <SRS>EPSG:4986</SRS>
+      <SRS>EPSG:4987</SRS>
+      <SRS>EPSG:4988</SRS>
+      <SRS>EPSG:4989</SRS>
+      <SRS>EPSG:4990</SRS>
+      <SRS>EPSG:4991</SRS>
+      <SRS>EPSG:4992</SRS>
+      <SRS>EPSG:4993</SRS>
+      <SRS>EPSG:4994</SRS>
+      <SRS>EPSG:4995</SRS>
+      <SRS>EPSG:4996</SRS>
+      <SRS>EPSG:4997</SRS>
+      <SRS>EPSG:4998</SRS>
+      <SRS>EPSG:4999</SRS>
+      <SRS>EPSG:5600</SRS>
+      <SRS>EPSG:5601</SRS>
+      <SRS>EPSG:5602</SRS>
+      <SRS>EPSG:5603</SRS>
+      <SRS>EPSG:5604</SRS>
+      <SRS>EPSG:5605</SRS>
+      <SRS>EPSG:5606</SRS>
+      <SRS>EPSG:5607</SRS>
+      <SRS>EPSG:5608</SRS>
+      <SRS>EPSG:5609</SRS>
+      <SRS>EPSG:5701</SRS>
+      <SRS>EPSG:5702</SRS>
+      <SRS>EPSG:5703</SRS>
+      <SRS>EPSG:5704</SRS>
+      <SRS>EPSG:5705</SRS>
+      <SRS>EPSG:5706</SRS>
+      <SRS>EPSG:5709</SRS>
+      <SRS>EPSG:5710</SRS>
+      <SRS>EPSG:5711</SRS>
+      <SRS>EPSG:5712</SRS>
+      <SRS>EPSG:5713</SRS>
+      <SRS>EPSG:5714</SRS>
+      <SRS>EPSG:5715</SRS>
+      <SRS>EPSG:5716</SRS>
+      <SRS>EPSG:5717</SRS>
+      <SRS>EPSG:5718</SRS>
+      <SRS>EPSG:5719</SRS>
+      <SRS>EPSG:5720</SRS>
+      <SRS>EPSG:5721</SRS>
+      <SRS>EPSG:5722</SRS>
+      <SRS>EPSG:5723</SRS>
+      <SRS>EPSG:5724</SRS>
+      <SRS>EPSG:5725</SRS>
+      <SRS>EPSG:5726</SRS>
+      <SRS>EPSG:5727</SRS>
+      <SRS>EPSG:5728</SRS>
+      <SRS>EPSG:5729</SRS>
+      <SRS>EPSG:5730</SRS>
+      <SRS>EPSG:5731</SRS>
+      <SRS>EPSG:5732</SRS>
+      <SRS>EPSG:5733</SRS>
+      <SRS>EPSG:5734</SRS>
+      <SRS>EPSG:5735</SRS>
+      <SRS>EPSG:5736</SRS>
+      <SRS>EPSG:5737</SRS>
+      <SRS>EPSG:5738</SRS>
+      <SRS>EPSG:5739</SRS>
+      <SRS>EPSG:5740</SRS>
+      <SRS>EPSG:5741</SRS>
+      <SRS>EPSG:5742</SRS>
+      <SRS>EPSG:5743</SRS>
+      <SRS>EPSG:5744</SRS>
+      <SRS>EPSG:5745</SRS>
+      <SRS>EPSG:5746</SRS>
+      <SRS>EPSG:5747</SRS>
+      <SRS>EPSG:5748</SRS>
+      <SRS>EPSG:5749</SRS>
+      <SRS>EPSG:5750</SRS>
+      <SRS>EPSG:5751</SRS>
+      <SRS>EPSG:5752</SRS>
+      <SRS>EPSG:5753</SRS>
+      <SRS>EPSG:5754</SRS>
+      <SRS>EPSG:5755</SRS>
+      <SRS>EPSG:5756</SRS>
+      <SRS>EPSG:5757</SRS>
+      <SRS>EPSG:5758</SRS>
+      <SRS>EPSG:5759</SRS>
+      <SRS>EPSG:5760</SRS>
+      <SRS>EPSG:5761</SRS>
+      <SRS>EPSG:5762</SRS>
+      <SRS>EPSG:5763</SRS>
+      <SRS>EPSG:5764</SRS>
+      <SRS>EPSG:5765</SRS>
+      <SRS>EPSG:5766</SRS>
+      <SRS>EPSG:5767</SRS>
+      <SRS>EPSG:5768</SRS>
+      <SRS>EPSG:5769</SRS>
+      <SRS>EPSG:5770</SRS>
+      <SRS>EPSG:5771</SRS>
+      <SRS>EPSG:5772</SRS>
+      <SRS>EPSG:5773</SRS>
+      <SRS>EPSG:5774</SRS>
+      <SRS>EPSG:5775</SRS>
+      <SRS>EPSG:5776</SRS>
+      <SRS>EPSG:5777</SRS>
+      <SRS>EPSG:5778</SRS>
+      <SRS>EPSG:5779</SRS>
+      <SRS>EPSG:5780</SRS>
+      <SRS>EPSG:5781</SRS>
+      <SRS>EPSG:5782</SRS>
+      <SRS>EPSG:5783</SRS>
+      <SRS>EPSG:5784</SRS>
+      <SRS>EPSG:5785</SRS>
+      <SRS>EPSG:5786</SRS>
+      <SRS>EPSG:5787</SRS>
+      <SRS>EPSG:5788</SRS>
+      <SRS>EPSG:5789</SRS>
+      <SRS>EPSG:5790</SRS>
+      <SRS>EPSG:5791</SRS>
+      <SRS>EPSG:5792</SRS>
+      <SRS>EPSG:5793</SRS>
+      <SRS>EPSG:5794</SRS>
+      <SRS>EPSG:5795</SRS>
+      <SRS>EPSG:5796</SRS>
+      <SRS>EPSG:5797</SRS>
+      <SRS>EPSG:5798</SRS>
+      <SRS>EPSG:5799</SRS>
+      <SRS>EPSG:5800</SRS>
+      <SRS>EPSG:5801</SRS>
+      <SRS>EPSG:5802</SRS>
+      <SRS>EPSG:5803</SRS>
+      <SRS>EPSG:5804</SRS>
+      <SRS>EPSG:5805</SRS>
+      <SRS>EPSG:5806</SRS>
+      <SRS>EPSG:5807</SRS>
+      <SRS>EPSG:5808</SRS>
+      <SRS>EPSG:5809</SRS>
+      <SRS>EPSG:5810</SRS>
+      <SRS>EPSG:5811</SRS>
+      <SRS>EPSG:5812</SRS>
+      <SRS>EPSG:5813</SRS>
+      <SRS>EPSG:5814</SRS>
+      <SRS>EPSG:5815</SRS>
+      <SRS>EPSG:5816</SRS>
+      <SRS>EPSG:5817</SRS>
+      <SRS>EPSG:5818</SRS>
+      <SRS>EPSG:7400</SRS>
+      <SRS>EPSG:7401</SRS>
+      <SRS>EPSG:7402</SRS>
+      <SRS>EPSG:7403</SRS>
+      <SRS>EPSG:7404</SRS>
+      <SRS>EPSG:7405</SRS>
+      <SRS>EPSG:7406</SRS>
+      <SRS>EPSG:7407</SRS>
+      <SRS>EPSG:7408</SRS>
+      <SRS>EPSG:7409</SRS>
+      <SRS>EPSG:7410</SRS>
+      <SRS>EPSG:7411</SRS>
+      <SRS>EPSG:7412</SRS>
+      <SRS>EPSG:7413</SRS>
+      <SRS>EPSG:7414</SRS>
+      <SRS>EPSG:7415</SRS>
+      <SRS>EPSG:7416</SRS>
+      <SRS>EPSG:7417</SRS>
+      <SRS>EPSG:7418</SRS>
+      <SRS>EPSG:7419</SRS>
+      <SRS>EPSG:7420</SRS>
+      <SRS>EPSG:20004</SRS>
+      <SRS>EPSG:20005</SRS>
+      <SRS>EPSG:20006</SRS>
+      <SRS>EPSG:20007</SRS>
+      <SRS>EPSG:20008</SRS>
+      <SRS>EPSG:20009</SRS>
+      <SRS>EPSG:20010</SRS>
+      <SRS>EPSG:20011</SRS>
+      <SRS>EPSG:20012</SRS>
+      <SRS>EPSG:20013</SRS>
+      <SRS>EPSG:20014</SRS>
+      <SRS>EPSG:20015</SRS>
+      <SRS>EPSG:20016</SRS>
+      <SRS>EPSG:20017</SRS>
+      <SRS>EPSG:20018</SRS>
+      <SRS>EPSG:20019</SRS>
+      <SRS>EPSG:20020</SRS>
+      <SRS>EPSG:20021</SRS>
+      <SRS>EPSG:20022</SRS>
+      <SRS>EPSG:20023</SRS>
+      <SRS>EPSG:20024</SRS>
+      <SRS>EPSG:20025</SRS>
+      <SRS>EPSG:20026</SRS>
+      <SRS>EPSG:20027</SRS>
+      <SRS>EPSG:20028</SRS>
+      <SRS>EPSG:20029</SRS>
+      <SRS>EPSG:20030</SRS>
+      <SRS>EPSG:20031</SRS>
+      <SRS>EPSG:20032</SRS>
+      <SRS>EPSG:20064</SRS>
+      <SRS>EPSG:20065</SRS>
+      <SRS>EPSG:20066</SRS>
+      <SRS>EPSG:20067</SRS>
+      <SRS>EPSG:20068</SRS>
+      <SRS>EPSG:20069</SRS>
+      <SRS>EPSG:20070</SRS>
+      <SRS>EPSG:20071</SRS>
+      <SRS>EPSG:20072</SRS>
+      <SRS>EPSG:20073</SRS>
+      <SRS>EPSG:20074</SRS>
+      <SRS>EPSG:20075</SRS>
+      <SRS>EPSG:20076</SRS>
+      <SRS>EPSG:20077</SRS>
+      <SRS>EPSG:20078</SRS>
+      <SRS>EPSG:20079</SRS>
+      <SRS>EPSG:20080</SRS>
+      <SRS>EPSG:20081</SRS>
+      <SRS>EPSG:20082</SRS>
+      <SRS>EPSG:20083</SRS>
+      <SRS>EPSG:20084</SRS>
+      <SRS>EPSG:20085</SRS>
+      <SRS>EPSG:20086</SRS>
+      <SRS>EPSG:20087</SRS>
+      <SRS>EPSG:20088</SRS>
+      <SRS>EPSG:20089</SRS>
+      <SRS>EPSG:20090</SRS>
+      <SRS>EPSG:20091</SRS>
+      <SRS>EPSG:20092</SRS>
+      <SRS>EPSG:20135</SRS>
+      <SRS>EPSG:20136</SRS>
+      <SRS>EPSG:20137</SRS>
+      <SRS>EPSG:20138</SRS>
+      <SRS>EPSG:20248</SRS>
+      <SRS>EPSG:20249</SRS>
+      <SRS>EPSG:20250</SRS>
+      <SRS>EPSG:20251</SRS>
+      <SRS>EPSG:20252</SRS>
+      <SRS>EPSG:20253</SRS>
+      <SRS>EPSG:20254</SRS>
+      <SRS>EPSG:20255</SRS>
+      <SRS>EPSG:20256</SRS>
+      <SRS>EPSG:20257</SRS>
+      <SRS>EPSG:20258</SRS>
+      <SRS>EPSG:20348</SRS>
+      <SRS>EPSG:20349</SRS>
+      <SRS>EPSG:20350</SRS>
+      <SRS>EPSG:20351</SRS>
+      <SRS>EPSG:20352</SRS>
+      <SRS>EPSG:20353</SRS>
+      <SRS>EPSG:20354</SRS>
+      <SRS>EPSG:20355</SRS>
+      <SRS>EPSG:20356</SRS>
+      <SRS>EPSG:20357</SRS>
+      <SRS>EPSG:20358</SRS>
+      <SRS>EPSG:20436</SRS>
+      <SRS>EPSG:20437</SRS>
+      <SRS>EPSG:20438</SRS>
+      <SRS>EPSG:20439</SRS>
+      <SRS>EPSG:20440</SRS>
+      <SRS>EPSG:20499</SRS>
+      <SRS>EPSG:20538</SRS>
+      <SRS>EPSG:20539</SRS>
+      <SRS>EPSG:20790</SRS>
+      <SRS>EPSG:20791</SRS>
+      <SRS>EPSG:20822</SRS>
+      <SRS>EPSG:20823</SRS>
+      <SRS>EPSG:20824</SRS>
+      <SRS>EPSG:20934</SRS>
+      <SRS>EPSG:20935</SRS>
+      <SRS>EPSG:20936</SRS>
+      <SRS>EPSG:21035</SRS>
+      <SRS>EPSG:21036</SRS>
+      <SRS>EPSG:21037</SRS>
+      <SRS>EPSG:21095</SRS>
+      <SRS>EPSG:21096</SRS>
+      <SRS>EPSG:21097</SRS>
+      <SRS>EPSG:21100</SRS>
+      <SRS>EPSG:21148</SRS>
+      <SRS>EPSG:21149</SRS>
+      <SRS>EPSG:21150</SRS>
+      <SRS>EPSG:21291</SRS>
+      <SRS>EPSG:21292</SRS>
+      <SRS>EPSG:21413</SRS>
+      <SRS>EPSG:21414</SRS>
+      <SRS>EPSG:21415</SRS>
+      <SRS>EPSG:21416</SRS>
+      <SRS>EPSG:21417</SRS>
+      <SRS>EPSG:21418</SRS>
+      <SRS>EPSG:21419</SRS>
+      <SRS>EPSG:21420</SRS>
+      <SRS>EPSG:21421</SRS>
+      <SRS>EPSG:21422</SRS>
+      <SRS>EPSG:21423</SRS>
+      <SRS>EPSG:21453</SRS>
+      <SRS>EPSG:21454</SRS>
+      <SRS>EPSG:21455</SRS>
+      <SRS>EPSG:21456</SRS>
+      <SRS>EPSG:21457</SRS>
+      <SRS>EPSG:21458</SRS>
+      <SRS>EPSG:21459</SRS>
+      <SRS>EPSG:21460</SRS>
+      <SRS>EPSG:21461</SRS>
+      <SRS>EPSG:21462</SRS>
+      <SRS>EPSG:21463</SRS>
+      <SRS>EPSG:21473</SRS>
+      <SRS>EPSG:21474</SRS>
+      <SRS>EPSG:21475</SRS>
+      <SRS>EPSG:21476</SRS>
+      <SRS>EPSG:21477</SRS>
+      <SRS>EPSG:21478</SRS>
+      <SRS>EPSG:21479</SRS>
+      <SRS>EPSG:21480</SRS>
+      <SRS>EPSG:21481</SRS>
+      <SRS>EPSG:21482</SRS>
+      <SRS>EPSG:21483</SRS>
+      <SRS>EPSG:21500</SRS>
+      <SRS>EPSG:21780</SRS>
+      <SRS>EPSG:21781</SRS>
+      <SRS>EPSG:21817</SRS>
+      <SRS>EPSG:21818</SRS>
+      <SRS>EPSG:21891</SRS>
+      <SRS>EPSG:21892</SRS>
+      <SRS>EPSG:21893</SRS>
+      <SRS>EPSG:21894</SRS>
+      <SRS>EPSG:21896</SRS>
+      <SRS>EPSG:21897</SRS>
+      <SRS>EPSG:21898</SRS>
+      <SRS>EPSG:21899</SRS>
+      <SRS>EPSG:22032</SRS>
+      <SRS>EPSG:22033</SRS>
+      <SRS>EPSG:22091</SRS>
+      <SRS>EPSG:22092</SRS>
+      <SRS>EPSG:22171</SRS>
+      <SRS>EPSG:22172</SRS>
+      <SRS>EPSG:22173</SRS>
+      <SRS>EPSG:22174</SRS>
+      <SRS>EPSG:22175</SRS>
+      <SRS>EPSG:22176</SRS>
+      <SRS>EPSG:22177</SRS>
+      <SRS>EPSG:22181</SRS>
+      <SRS>EPSG:22182</SRS>
+      <SRS>EPSG:22183</SRS>
+      <SRS>EPSG:22184</SRS>
+      <SRS>EPSG:22185</SRS>
+      <SRS>EPSG:22186</SRS>
+      <SRS>EPSG:22187</SRS>
+      <SRS>EPSG:22191</SRS>
+      <SRS>EPSG:22192</SRS>
+      <SRS>EPSG:22193</SRS>
+      <SRS>EPSG:22194</SRS>
+      <SRS>EPSG:22195</SRS>
+      <SRS>EPSG:22196</SRS>
+      <SRS>EPSG:22197</SRS>
+      <SRS>EPSG:22234</SRS>
+      <SRS>EPSG:22235</SRS>
+      <SRS>EPSG:22236</SRS>
+      <SRS>EPSG:22275</SRS>
+      <SRS>EPSG:22277</SRS>
+      <SRS>EPSG:22279</SRS>
+      <SRS>EPSG:22281</SRS>
+      <SRS>EPSG:22283</SRS>
+      <SRS>EPSG:22285</SRS>
+      <SRS>EPSG:22287</SRS>
+      <SRS>EPSG:22289</SRS>
+      <SRS>EPSG:22291</SRS>
+      <SRS>EPSG:22293</SRS>
+      <SRS>EPSG:22300</SRS>
+      <SRS>EPSG:22332</SRS>
+      <SRS>EPSG:22391</SRS>
+      <SRS>EPSG:22392</SRS>
+      <SRS>EPSG:22521</SRS>
+      <SRS>EPSG:22522</SRS>
+      <SRS>EPSG:22523</SRS>
+      <SRS>EPSG:22524</SRS>
+      <SRS>EPSG:22525</SRS>
+      <SRS>EPSG:22700</SRS>
+      <SRS>EPSG:22770</SRS>
+      <SRS>EPSG:22780</SRS>
+      <SRS>EPSG:22832</SRS>
+      <SRS>EPSG:22991</SRS>
+      <SRS>EPSG:22992</SRS>
+      <SRS>EPSG:22993</SRS>
+      <SRS>EPSG:22994</SRS>
+      <SRS>EPSG:23028</SRS>
+      <SRS>EPSG:23029</SRS>
+      <SRS>EPSG:23030</SRS>
+      <SRS>EPSG:23031</SRS>
+      <SRS>EPSG:23032</SRS>
+      <SRS>EPSG:23033</SRS>
+      <SRS>EPSG:23034</SRS>
+      <SRS>EPSG:23035</SRS>
+      <SRS>EPSG:23036</SRS>
+      <SRS>EPSG:23037</SRS>
+      <SRS>EPSG:23038</SRS>
+      <SRS>EPSG:23090</SRS>
+      <SRS>EPSG:23095</SRS>
+      <SRS>EPSG:23239</SRS>
+      <SRS>EPSG:23240</SRS>
+      <SRS>EPSG:23433</SRS>
+      <SRS>EPSG:23700</SRS>
+      <SRS>EPSG:23846</SRS>
+      <SRS>EPSG:23847</SRS>
+      <SRS>EPSG:23848</SRS>
+      <SRS>EPSG:23849</SRS>
+      <SRS>EPSG:23850</SRS>
+      <SRS>EPSG:23851</SRS>
+      <SRS>EPSG:23852</SRS>
+      <SRS>EPSG:23853</SRS>
+      <SRS>EPSG:23866</SRS>
+      <SRS>EPSG:23867</SRS>
+      <SRS>EPSG:23868</SRS>
+      <SRS>EPSG:23869</SRS>
+      <SRS>EPSG:23870</SRS>
+      <SRS>EPSG:23871</SRS>
+      <SRS>EPSG:23872</SRS>
+      <SRS>EPSG:23877</SRS>
+      <SRS>EPSG:23878</SRS>
+      <SRS>EPSG:23879</SRS>
+      <SRS>EPSG:23880</SRS>
+      <SRS>EPSG:23881</SRS>
+      <SRS>EPSG:23882</SRS>
+      <SRS>EPSG:23883</SRS>
+      <SRS>EPSG:23884</SRS>
+      <SRS>EPSG:23886</SRS>
+      <SRS>EPSG:23887</SRS>
+      <SRS>EPSG:23888</SRS>
+      <SRS>EPSG:23889</SRS>
+      <SRS>EPSG:23890</SRS>
+      <SRS>EPSG:23891</SRS>
+      <SRS>EPSG:23892</SRS>
+      <SRS>EPSG:23893</SRS>
+      <SRS>EPSG:23894</SRS>
+      <SRS>EPSG:23946</SRS>
+      <SRS>EPSG:23947</SRS>
+      <SRS>EPSG:23948</SRS>
+      <SRS>EPSG:24047</SRS>
+      <SRS>EPSG:24048</SRS>
+      <SRS>EPSG:24100</SRS>
+      <SRS>EPSG:24200</SRS>
+      <SRS>EPSG:24305</SRS>
+      <SRS>EPSG:24306</SRS>
+      <SRS>EPSG:24311</SRS>
+      <SRS>EPSG:24312</SRS>
+      <SRS>EPSG:24313</SRS>
+      <SRS>EPSG:24342</SRS>
+      <SRS>EPSG:24343</SRS>
+      <SRS>EPSG:24344</SRS>
+      <SRS>EPSG:24345</SRS>
+      <SRS>EPSG:24346</SRS>
+      <SRS>EPSG:24347</SRS>
+      <SRS>EPSG:24370</SRS>
+      <SRS>EPSG:24371</SRS>
+      <SRS>EPSG:24372</SRS>
+      <SRS>EPSG:24373</SRS>
+      <SRS>EPSG:24374</SRS>
+      <SRS>EPSG:24375</SRS>
+      <SRS>EPSG:24376</SRS>
+      <SRS>EPSG:24377</SRS>
+      <SRS>EPSG:24378</SRS>
+      <SRS>EPSG:24379</SRS>
+      <SRS>EPSG:24380</SRS>
+      <SRS>EPSG:24381</SRS>
+      <SRS>EPSG:24382</SRS>
+      <SRS>EPSG:24383</SRS>
+      <SRS>EPSG:24500</SRS>
+      <SRS>EPSG:24547</SRS>
+      <SRS>EPSG:24548</SRS>
+      <SRS>EPSG:24571</SRS>
+      <SRS>EPSG:24600</SRS>
+      <SRS>EPSG:24718</SRS>
+      <SRS>EPSG:24719</SRS>
+      <SRS>EPSG:24720</SRS>
+      <SRS>EPSG:24817</SRS>
+      <SRS>EPSG:24818</SRS>
+      <SRS>EPSG:24819</SRS>
+      <SRS>EPSG:24820</SRS>
+      <SRS>EPSG:24821</SRS>
+      <SRS>EPSG:24877</SRS>
+      <SRS>EPSG:24878</SRS>
+      <SRS>EPSG:24879</SRS>
+      <SRS>EPSG:24880</SRS>
+      <SRS>EPSG:24881</SRS>
+      <SRS>EPSG:24882</SRS>
+      <SRS>EPSG:24891</SRS>
+      <SRS>EPSG:24892</SRS>
+      <SRS>EPSG:24893</SRS>
+      <SRS>EPSG:25000</SRS>
+      <SRS>EPSG:25231</SRS>
+      <SRS>EPSG:25391</SRS>
+      <SRS>EPSG:25392</SRS>
+      <SRS>EPSG:25393</SRS>
+      <SRS>EPSG:25394</SRS>
+      <SRS>EPSG:25395</SRS>
+      <SRS>EPSG:25700</SRS>
+      <SRS>EPSG:25828</SRS>
+      <SRS>EPSG:25829</SRS>
+      <SRS>EPSG:25830</SRS>
+      <SRS>EPSG:25831</SRS>
+      <SRS>EPSG:25832</SRS>
+      <SRS>EPSG:25833</SRS>
+      <SRS>EPSG:25834</SRS>
+      <SRS>EPSG:25835</SRS>
+      <SRS>EPSG:25836</SRS>
+      <SRS>EPSG:25837</SRS>
+      <SRS>EPSG:25838</SRS>
+      <SRS>EPSG:25884</SRS>
+      <SRS>EPSG:25932</SRS>
+      <SRS>EPSG:26191</SRS>
+      <SRS>EPSG:26192</SRS>
+      <SRS>EPSG:26193</SRS>
+      <SRS>EPSG:26194</SRS>
+      <SRS>EPSG:26195</SRS>
+      <SRS>EPSG:26237</SRS>
+      <SRS>EPSG:26331</SRS>
+      <SRS>EPSG:26332</SRS>
+      <SRS>EPSG:26391</SRS>
+      <SRS>EPSG:26392</SRS>
+      <SRS>EPSG:26393</SRS>
+      <SRS>EPSG:26432</SRS>
+      <SRS>EPSG:26591</SRS>
+      <SRS>EPSG:26592</SRS>
+      <SRS>EPSG:26632</SRS>
+      <SRS>EPSG:26692</SRS>
+      <SRS>EPSG:26701</SRS>
+      <SRS>EPSG:26702</SRS>
+      <SRS>EPSG:26703</SRS>
+      <SRS>EPSG:26704</SRS>
+      <SRS>EPSG:26705</SRS>
+      <SRS>EPSG:26706</SRS>
+      <SRS>EPSG:26707</SRS>
+      <SRS>EPSG:26708</SRS>
+      <SRS>EPSG:26709</SRS>
+      <SRS>EPSG:26710</SRS>
+      <SRS>EPSG:26711</SRS>
+      <SRS>EPSG:26712</SRS>
+      <SRS>EPSG:26713</SRS>
+      <SRS>EPSG:26714</SRS>
+      <SRS>EPSG:26715</SRS>
+      <SRS>EPSG:26716</SRS>
+      <SRS>EPSG:26717</SRS>
+      <SRS>EPSG:26718</SRS>
+      <SRS>EPSG:26719</SRS>
+      <SRS>EPSG:26720</SRS>
+      <SRS>EPSG:26721</SRS>
+      <SRS>EPSG:26722</SRS>
+      <SRS>EPSG:26729</SRS>
+      <SRS>EPSG:26730</SRS>
+      <SRS>EPSG:26731</SRS>
+      <SRS>EPSG:26732</SRS>
+      <SRS>EPSG:26733</SRS>
+      <SRS>EPSG:26734</SRS>
+      <SRS>EPSG:26735</SRS>
+      <SRS>EPSG:26736</SRS>
+      <SRS>EPSG:26737</SRS>
+      <SRS>EPSG:26738</SRS>
+      <SRS>EPSG:26739</SRS>
+      <SRS>EPSG:26740</SRS>
+      <SRS>EPSG:26741</SRS>
+      <SRS>EPSG:26742</SRS>
+      <SRS>EPSG:26743</SRS>
+      <SRS>EPSG:26744</SRS>
+      <SRS>EPSG:26745</SRS>
+      <SRS>EPSG:26746</SRS>
+      <SRS>EPSG:26747</SRS>
+      <SRS>EPSG:26748</SRS>
+      <SRS>EPSG:26749</SRS>
+      <SRS>EPSG:26750</SRS>
+      <SRS>EPSG:26751</SRS>
+      <SRS>EPSG:26752</SRS>
+      <SRS>EPSG:26753</SRS>
+      <SRS>EPSG:26754</SRS>
+      <SRS>EPSG:26755</SRS>
+      <SRS>EPSG:26756</SRS>
+      <SRS>EPSG:26757</SRS>
+      <SRS>EPSG:26758</SRS>
+      <SRS>EPSG:26759</SRS>
+      <SRS>EPSG:26760</SRS>
+      <SRS>EPSG:26766</SRS>
+      <SRS>EPSG:26767</SRS>
+      <SRS>EPSG:26768</SRS>
+      <SRS>EPSG:26769</SRS>
+      <SRS>EPSG:26770</SRS>
+      <SRS>EPSG:26771</SRS>
+      <SRS>EPSG:26772</SRS>
+      <SRS>EPSG:26773</SRS>
+      <SRS>EPSG:26774</SRS>
+      <SRS>EPSG:26775</SRS>
+      <SRS>EPSG:26776</SRS>
+      <SRS>EPSG:26777</SRS>
+      <SRS>EPSG:26778</SRS>
+      <SRS>EPSG:26779</SRS>
+      <SRS>EPSG:26780</SRS>
+      <SRS>EPSG:26781</SRS>
+      <SRS>EPSG:26782</SRS>
+      <SRS>EPSG:26783</SRS>
+      <SRS>EPSG:26784</SRS>
+      <SRS>EPSG:26785</SRS>
+      <SRS>EPSG:26786</SRS>
+      <SRS>EPSG:26787</SRS>
+      <SRS>EPSG:26791</SRS>
+      <SRS>EPSG:26792</SRS>
+      <SRS>EPSG:26793</SRS>
+      <SRS>EPSG:26794</SRS>
+      <SRS>EPSG:26795</SRS>
+      <SRS>EPSG:26796</SRS>
+      <SRS>EPSG:26797</SRS>
+      <SRS>EPSG:26798</SRS>
+      <SRS>EPSG:26799</SRS>
+      <SRS>EPSG:26801</SRS>
+      <SRS>EPSG:26802</SRS>
+      <SRS>EPSG:26803</SRS>
+      <SRS>EPSG:26811</SRS>
+      <SRS>EPSG:26812</SRS>
+      <SRS>EPSG:26813</SRS>
+      <SRS>EPSG:26901</SRS>
+      <SRS>EPSG:26902</SRS>
+      <SRS>EPSG:26903</SRS>
+      <SRS>EPSG:26904</SRS>
+      <SRS>EPSG:26905</SRS>
+      <SRS>EPSG:26906</SRS>
+      <SRS>EPSG:26907</SRS>
+      <SRS>EPSG:26908</SRS>
+      <SRS>EPSG:26909</SRS>
+      <SRS>EPSG:26910</SRS>
+      <SRS>EPSG:26911</SRS>
+      <SRS>EPSG:26912</SRS>
+      <SRS>EPSG:26913</SRS>
+      <SRS>EPSG:26914</SRS>
+      <SRS>EPSG:26915</SRS>
+      <SRS>EPSG:26916</SRS>
+      <SRS>EPSG:26917</SRS>
+      <SRS>EPSG:26918</SRS>
+      <SRS>EPSG:26919</SRS>
+      <SRS>EPSG:26920</SRS>
+      <SRS>EPSG:26921</SRS>
+      <SRS>EPSG:26922</SRS>
+      <SRS>EPSG:26923</SRS>
+      <SRS>EPSG:26929</SRS>
+      <SRS>EPSG:26930</SRS>
+      <SRS>EPSG:26931</SRS>
+      <SRS>EPSG:26932</SRS>
+      <SRS>EPSG:26933</SRS>
+      <SRS>EPSG:26934</SRS>
+      <SRS>EPSG:26935</SRS>
+      <SRS>EPSG:26936</SRS>
+      <SRS>EPSG:26937</SRS>
+      <SRS>EPSG:26938</SRS>
+      <SRS>EPSG:26939</SRS>
+      <SRS>EPSG:26940</SRS>
+      <SRS>EPSG:26941</SRS>
+      <SRS>EPSG:26942</SRS>
+      <SRS>EPSG:26943</SRS>
+      <SRS>EPSG:26944</SRS>
+      <SRS>EPSG:26945</SRS>
+      <SRS>EPSG:26946</SRS>
+      <SRS>EPSG:26948</SRS>
+      <SRS>EPSG:26949</SRS>
+      <SRS>EPSG:26950</SRS>
+      <SRS>EPSG:26951</SRS>
+      <SRS>EPSG:26952</SRS>
+      <SRS>EPSG:26953</SRS>
+      <SRS>EPSG:26954</SRS>
+      <SRS>EPSG:26955</SRS>
+      <SRS>EPSG:26956</SRS>
+      <SRS>EPSG:26957</SRS>
+      <SRS>EPSG:26958</SRS>
+      <SRS>EPSG:26959</SRS>
+      <SRS>EPSG:26960</SRS>
+      <SRS>EPSG:26961</SRS>
+      <SRS>EPSG:26962</SRS>
+      <SRS>EPSG:26963</SRS>
+      <SRS>EPSG:26964</SRS>
+      <SRS>EPSG:26965</SRS>
+      <SRS>EPSG:26966</SRS>
+      <SRS>EPSG:26967</SRS>
+      <SRS>EPSG:26968</SRS>
+      <SRS>EPSG:26969</SRS>
+      <SRS>EPSG:26970</SRS>
+      <SRS>EPSG:26971</SRS>
+      <SRS>EPSG:26972</SRS>
+      <SRS>EPSG:26973</SRS>
+      <SRS>EPSG:26974</SRS>
+      <SRS>EPSG:26975</SRS>
+      <SRS>EPSG:26976</SRS>
+      <SRS>EPSG:26977</SRS>
+      <SRS>EPSG:26978</SRS>
+      <SRS>EPSG:26979</SRS>
+      <SRS>EPSG:26980</SRS>
+      <SRS>EPSG:26981</SRS>
+      <SRS>EPSG:26982</SRS>
+      <SRS>EPSG:26983</SRS>
+      <SRS>EPSG:26984</SRS>
+      <SRS>EPSG:26985</SRS>
+      <SRS>EPSG:26986</SRS>
+      <SRS>EPSG:26987</SRS>
+      <SRS>EPSG:26988</SRS>
+      <SRS>EPSG:26989</SRS>
+      <SRS>EPSG:26990</SRS>
+      <SRS>EPSG:26991</SRS>
+      <SRS>EPSG:26992</SRS>
+      <SRS>EPSG:26993</SRS>
+      <SRS>EPSG:26994</SRS>
+      <SRS>EPSG:26995</SRS>
+      <SRS>EPSG:26996</SRS>
+      <SRS>EPSG:26997</SRS>
+      <SRS>EPSG:26998</SRS>
+      <SRS>EPSG:27037</SRS>
+      <SRS>EPSG:27038</SRS>
+      <SRS>EPSG:27039</SRS>
+      <SRS>EPSG:27040</SRS>
+      <SRS>EPSG:27120</SRS>
+      <SRS>EPSG:27200</SRS>
+      <SRS>EPSG:27205</SRS>
+      <SRS>EPSG:27206</SRS>
+      <SRS>EPSG:27207</SRS>
+      <SRS>EPSG:27208</SRS>
+      <SRS>EPSG:27209</SRS>
+      <SRS>EPSG:27210</SRS>
+      <SRS>EPSG:27211</SRS>
+      <SRS>EPSG:27212</SRS>
+      <SRS>EPSG:27213</SRS>
+      <SRS>EPSG:27214</SRS>
+      <SRS>EPSG:27215</SRS>
+      <SRS>EPSG:27216</SRS>
+      <SRS>EPSG:27217</SRS>
+      <SRS>EPSG:27218</SRS>
+      <SRS>EPSG:27219</SRS>
+      <SRS>EPSG:27220</SRS>
+      <SRS>EPSG:27221</SRS>
+      <SRS>EPSG:27222</SRS>
+      <SRS>EPSG:27223</SRS>
+      <SRS>EPSG:27224</SRS>
+      <SRS>EPSG:27225</SRS>
+      <SRS>EPSG:27226</SRS>
+      <SRS>EPSG:27227</SRS>
+      <SRS>EPSG:27228</SRS>
+      <SRS>EPSG:27229</SRS>
+      <SRS>EPSG:27230</SRS>
+      <SRS>EPSG:27231</SRS>
+      <SRS>EPSG:27232</SRS>
+      <SRS>EPSG:27258</SRS>
+      <SRS>EPSG:27259</SRS>
+      <SRS>EPSG:27260</SRS>
+      <SRS>EPSG:27291</SRS>
+      <SRS>EPSG:27292</SRS>
+      <SRS>EPSG:27391</SRS>
+      <SRS>EPSG:27392</SRS>
+      <SRS>EPSG:27393</SRS>
+      <SRS>EPSG:27394</SRS>
+      <SRS>EPSG:27395</SRS>
+      <SRS>EPSG:27396</SRS>
+      <SRS>EPSG:27397</SRS>
+      <SRS>EPSG:27398</SRS>
+      <SRS>EPSG:27429</SRS>
+      <SRS>EPSG:27492</SRS>
+      <SRS>EPSG:27500</SRS>
+      <SRS>EPSG:27561</SRS>
+      <SRS>EPSG:27562</SRS>
+      <SRS>EPSG:27563</SRS>
+      <SRS>EPSG:27564</SRS>
+      <SRS>EPSG:27571</SRS>
+      <SRS>EPSG:27572</SRS>
+      <SRS>EPSG:27573</SRS>
+      <SRS>EPSG:27574</SRS>
+      <SRS>EPSG:27581</SRS>
+      <SRS>EPSG:27582</SRS>
+      <SRS>EPSG:27583</SRS>
+      <SRS>EPSG:27584</SRS>
+      <SRS>EPSG:27591</SRS>
+      <SRS>EPSG:27592</SRS>
+      <SRS>EPSG:27593</SRS>
+      <SRS>EPSG:27594</SRS>
+      <SRS>EPSG:27700</SRS>
+      <SRS>EPSG:28191</SRS>
+      <SRS>EPSG:28192</SRS>
+      <SRS>EPSG:28193</SRS>
+      <SRS>EPSG:28232</SRS>
+      <SRS>EPSG:28348</SRS>
+      <SRS>EPSG:28349</SRS>
+      <SRS>EPSG:28350</SRS>
+      <SRS>EPSG:28351</SRS>
+      <SRS>EPSG:28352</SRS>
+      <SRS>EPSG:28353</SRS>
+      <SRS>EPSG:28354</SRS>
+      <SRS>EPSG:28355</SRS>
+      <SRS>EPSG:28356</SRS>
+      <SRS>EPSG:28357</SRS>
+      <SRS>EPSG:28358</SRS>
+      <SRS>EPSG:28402</SRS>
+      <SRS>EPSG:28403</SRS>
+      <SRS>EPSG:28404</SRS>
+      <SRS>EPSG:28405</SRS>
+      <SRS>EPSG:28406</SRS>
+      <SRS>EPSG:28407</SRS>
+      <SRS>EPSG:28408</SRS>
+      <SRS>EPSG:28409</SRS>
+      <SRS>EPSG:28410</SRS>
+      <SRS>EPSG:28411</SRS>
+      <SRS>EPSG:28412</SRS>
+      <SRS>EPSG:28413</SRS>
+      <SRS>EPSG:28414</SRS>
+      <SRS>EPSG:28415</SRS>
+      <SRS>EPSG:28416</SRS>
+      <SRS>EPSG:28417</SRS>
+      <SRS>EPSG:28418</SRS>
+      <SRS>EPSG:28419</SRS>
+      <SRS>EPSG:28420</SRS>
+      <SRS>EPSG:28421</SRS>
+      <SRS>EPSG:28422</SRS>
+      <SRS>EPSG:28423</SRS>
+      <SRS>EPSG:28424</SRS>
+      <SRS>EPSG:28425</SRS>
+      <SRS>EPSG:28426</SRS>
+      <SRS>EPSG:28427</SRS>
+      <SRS>EPSG:28428</SRS>
+      <SRS>EPSG:28429</SRS>
+      <SRS>EPSG:28430</SRS>
+      <SRS>EPSG:28431</SRS>
+      <SRS>EPSG:28432</SRS>
+      <SRS>EPSG:28462</SRS>
+      <SRS>EPSG:28463</SRS>
+      <SRS>EPSG:28464</SRS>
+      <SRS>EPSG:28465</SRS>
+      <SRS>EPSG:28466</SRS>
+      <SRS>EPSG:28467</SRS>
+      <SRS>EPSG:28468</SRS>
+      <SRS>EPSG:28469</SRS>
+      <SRS>EPSG:28470</SRS>
+      <SRS>EPSG:28471</SRS>
+      <SRS>EPSG:28472</SRS>
+      <SRS>EPSG:28473</SRS>
+      <SRS>EPSG:28474</SRS>
+      <SRS>EPSG:28475</SRS>
+      <SRS>EPSG:28476</SRS>
+      <SRS>EPSG:28477</SRS>
+      <SRS>EPSG:28478</SRS>
+      <SRS>EPSG:28479</SRS>
+      <SRS>EPSG:28480</SRS>
+      <SRS>EPSG:28481</SRS>
+      <SRS>EPSG:28482</SRS>
+      <SRS>EPSG:28483</SRS>
+      <SRS>EPSG:28484</SRS>
+      <SRS>EPSG:28485</SRS>
+      <SRS>EPSG:28486</SRS>
+      <SRS>EPSG:28487</SRS>
+      <SRS>EPSG:28488</SRS>
+      <SRS>EPSG:28489</SRS>
+      <SRS>EPSG:28490</SRS>
+      <SRS>EPSG:28491</SRS>
+      <SRS>EPSG:28492</SRS>
+      <SRS>EPSG:28600</SRS>
+      <SRS>EPSG:28991</SRS>
+      <SRS>EPSG:28992</SRS>
+      <SRS>EPSG:29100</SRS>
+      <SRS>EPSG:29101</SRS>
+      <SRS>EPSG:29118</SRS>
+      <SRS>EPSG:29119</SRS>
+      <SRS>EPSG:29120</SRS>
+      <SRS>EPSG:29121</SRS>
+      <SRS>EPSG:29122</SRS>
+      <SRS>EPSG:29168</SRS>
+      <SRS>EPSG:29169</SRS>
+      <SRS>EPSG:29170</SRS>
+      <SRS>EPSG:29171</SRS>
+      <SRS>EPSG:29172</SRS>
+      <SRS>EPSG:29177</SRS>
+      <SRS>EPSG:29178</SRS>
+      <SRS>EPSG:29179</SRS>
+      <SRS>EPSG:29180</SRS>
+      <SRS>EPSG:29181</SRS>
+      <SRS>EPSG:29182</SRS>
+      <SRS>EPSG:29183</SRS>
+      <SRS>EPSG:29184</SRS>
+      <SRS>EPSG:29185</SRS>
+      <SRS>EPSG:29187</SRS>
+      <SRS>EPSG:29188</SRS>
+      <SRS>EPSG:29189</SRS>
+      <SRS>EPSG:29190</SRS>
+      <SRS>EPSG:29191</SRS>
+      <SRS>EPSG:29192</SRS>
+      <SRS>EPSG:29193</SRS>
+      <SRS>EPSG:29194</SRS>
+      <SRS>EPSG:29195</SRS>
+      <SRS>EPSG:29220</SRS>
+      <SRS>EPSG:29221</SRS>
+      <SRS>EPSG:29333</SRS>
+      <SRS>EPSG:29371</SRS>
+      <SRS>EPSG:29373</SRS>
+      <SRS>EPSG:29375</SRS>
+      <SRS>EPSG:29377</SRS>
+      <SRS>EPSG:29379</SRS>
+      <SRS>EPSG:29381</SRS>
+      <SRS>EPSG:29383</SRS>
+      <SRS>EPSG:29385</SRS>
+      <SRS>EPSG:29635</SRS>
+      <SRS>EPSG:29636</SRS>
+      <SRS>EPSG:29700</SRS>
+      <SRS>EPSG:29701</SRS>
+      <SRS>EPSG:29702</SRS>
+      <SRS>EPSG:29738</SRS>
+      <SRS>EPSG:29739</SRS>
+      <SRS>EPSG:29849</SRS>
+      <SRS>EPSG:29850</SRS>
+      <SRS>EPSG:29871</SRS>
+      <SRS>EPSG:29872</SRS>
+      <SRS>EPSG:29873</SRS>
+      <SRS>EPSG:29900</SRS>
+      <SRS>EPSG:29901</SRS>
+      <SRS>EPSG:29902</SRS>
+      <SRS>EPSG:29903</SRS>
+      <SRS>EPSG:30161</SRS>
+      <SRS>EPSG:30162</SRS>
+      <SRS>EPSG:30163</SRS>
+      <SRS>EPSG:30164</SRS>
+      <SRS>EPSG:30165</SRS>
+      <SRS>EPSG:30166</SRS>
+      <SRS>EPSG:30167</SRS>
+      <SRS>EPSG:30168</SRS>
+      <SRS>EPSG:30169</SRS>
+      <SRS>EPSG:30170</SRS>
+      <SRS>EPSG:30171</SRS>
+      <SRS>EPSG:30172</SRS>
+      <SRS>EPSG:30173</SRS>
+      <SRS>EPSG:30174</SRS>
+      <SRS>EPSG:30175</SRS>
+      <SRS>EPSG:30176</SRS>
+      <SRS>EPSG:30177</SRS>
+      <SRS>EPSG:30178</SRS>
+      <SRS>EPSG:30179</SRS>
+      <SRS>EPSG:30200</SRS>
+      <SRS>EPSG:30339</SRS>
+      <SRS>EPSG:30340</SRS>
+      <SRS>EPSG:30491</SRS>
+      <SRS>EPSG:30492</SRS>
+      <SRS>EPSG:30493</SRS>
+      <SRS>EPSG:30494</SRS>
+      <SRS>EPSG:30729</SRS>
+      <SRS>EPSG:30730</SRS>
+      <SRS>EPSG:30731</SRS>
+      <SRS>EPSG:30732</SRS>
+      <SRS>EPSG:30791</SRS>
+      <SRS>EPSG:30792</SRS>
+      <SRS>EPSG:30800</SRS>
+      <SRS>EPSG:31028</SRS>
+      <SRS>EPSG:31121</SRS>
+      <SRS>EPSG:31154</SRS>
+      <SRS>EPSG:31170</SRS>
+      <SRS>EPSG:31171</SRS>
+      <SRS>EPSG:31251</SRS>
+      <SRS>EPSG:31252</SRS>
+      <SRS>EPSG:31253</SRS>
+      <SRS>EPSG:31254</SRS>
+      <SRS>EPSG:31255</SRS>
+      <SRS>EPSG:31256</SRS>
+      <SRS>EPSG:31257</SRS>
+      <SRS>EPSG:31258</SRS>
+      <SRS>EPSG:31259</SRS>
+      <SRS>EPSG:31265</SRS>
+      <SRS>EPSG:31266</SRS>
+      <SRS>EPSG:31267</SRS>
+      <SRS>EPSG:31268</SRS>
+      <SRS>EPSG:31275</SRS>
+      <SRS>EPSG:31276</SRS>
+      <SRS>EPSG:31277</SRS>
+      <SRS>EPSG:31278</SRS>
+      <SRS>EPSG:31279</SRS>
+      <SRS>EPSG:31281</SRS>
+      <SRS>EPSG:31282</SRS>
+      <SRS>EPSG:31283</SRS>
+      <SRS>EPSG:31284</SRS>
+      <SRS>EPSG:31285</SRS>
+      <SRS>EPSG:31286</SRS>
+      <SRS>EPSG:31287</SRS>
+      <SRS>EPSG:31288</SRS>
+      <SRS>EPSG:31289</SRS>
+      <SRS>EPSG:31290</SRS>
+      <SRS>EPSG:31291</SRS>
+      <SRS>EPSG:31292</SRS>
+      <SRS>EPSG:31293</SRS>
+      <SRS>EPSG:31294</SRS>
+      <SRS>EPSG:31295</SRS>
+      <SRS>EPSG:31296</SRS>
+      <SRS>EPSG:31297</SRS>
+      <SRS>EPSG:31300</SRS>
+      <SRS>EPSG:31370</SRS>
+      <SRS>EPSG:31461</SRS>
+      <SRS>EPSG:31462</SRS>
+      <SRS>EPSG:31463</SRS>
+      <SRS>EPSG:31464</SRS>
+      <SRS>EPSG:31465</SRS>
+      <SRS>EPSG:31466</SRS>
+      <SRS>EPSG:31467</SRS>
+      <SRS>EPSG:31468</SRS>
+      <SRS>EPSG:31469</SRS>
+      <SRS>EPSG:31528</SRS>
+      <SRS>EPSG:31529</SRS>
+      <SRS>EPSG:31600</SRS>
+      <SRS>EPSG:31700</SRS>
+      <SRS>EPSG:31838</SRS>
+      <SRS>EPSG:31839</SRS>
+      <SRS>EPSG:31900</SRS>
+      <SRS>EPSG:31901</SRS>
+      <SRS>EPSG:31965</SRS>
+      <SRS>EPSG:31966</SRS>
+      <SRS>EPSG:31967</SRS>
+      <SRS>EPSG:31968</SRS>
+      <SRS>EPSG:31969</SRS>
+      <SRS>EPSG:31970</SRS>
+      <SRS>EPSG:31971</SRS>
+      <SRS>EPSG:31972</SRS>
+      <SRS>EPSG:31973</SRS>
+      <SRS>EPSG:31974</SRS>
+      <SRS>EPSG:31975</SRS>
+      <SRS>EPSG:31976</SRS>
+      <SRS>EPSG:31977</SRS>
+      <SRS>EPSG:31978</SRS>
+      <SRS>EPSG:31979</SRS>
+      <SRS>EPSG:31980</SRS>
+      <SRS>EPSG:31981</SRS>
+      <SRS>EPSG:31982</SRS>
+      <SRS>EPSG:31983</SRS>
+      <SRS>EPSG:31984</SRS>
+      <SRS>EPSG:31985</SRS>
+      <SRS>EPSG:31986</SRS>
+      <SRS>EPSG:31987</SRS>
+      <SRS>EPSG:31988</SRS>
+      <SRS>EPSG:31989</SRS>
+      <SRS>EPSG:31990</SRS>
+      <SRS>EPSG:31991</SRS>
+      <SRS>EPSG:31992</SRS>
+      <SRS>EPSG:31993</SRS>
+      <SRS>EPSG:31994</SRS>
+      <SRS>EPSG:31995</SRS>
+      <SRS>EPSG:31996</SRS>
+      <SRS>EPSG:31997</SRS>
+      <SRS>EPSG:31998</SRS>
+      <SRS>EPSG:31999</SRS>
+      <SRS>EPSG:32000</SRS>
+      <SRS>EPSG:32001</SRS>
+      <SRS>EPSG:32002</SRS>
+      <SRS>EPSG:32003</SRS>
+      <SRS>EPSG:32005</SRS>
+      <SRS>EPSG:32006</SRS>
+      <SRS>EPSG:32007</SRS>
+      <SRS>EPSG:32008</SRS>
+      <SRS>EPSG:32009</SRS>
+      <SRS>EPSG:32010</SRS>
+      <SRS>EPSG:32011</SRS>
+      <SRS>EPSG:32012</SRS>
+      <SRS>EPSG:32013</SRS>
+      <SRS>EPSG:32014</SRS>
+      <SRS>EPSG:32015</SRS>
+      <SRS>EPSG:32016</SRS>
+      <SRS>EPSG:32017</SRS>
+      <SRS>EPSG:32018</SRS>
+      <SRS>EPSG:32019</SRS>
+      <SRS>EPSG:32020</SRS>
+      <SRS>EPSG:32021</SRS>
+      <SRS>EPSG:32022</SRS>
+      <SRS>EPSG:32023</SRS>
+      <SRS>EPSG:32024</SRS>
+      <SRS>EPSG:32025</SRS>
+      <SRS>EPSG:32026</SRS>
+      <SRS>EPSG:32027</SRS>
+      <SRS>EPSG:32028</SRS>
+      <SRS>EPSG:32029</SRS>
+      <SRS>EPSG:32030</SRS>
+      <SRS>EPSG:32031</SRS>
+      <SRS>EPSG:32033</SRS>
+      <SRS>EPSG:32034</SRS>
+      <SRS>EPSG:32035</SRS>
+      <SRS>EPSG:32036</SRS>
+      <SRS>EPSG:32037</SRS>
+      <SRS>EPSG:32038</SRS>
+      <SRS>EPSG:32039</SRS>
+      <SRS>EPSG:32040</SRS>
+      <SRS>EPSG:32041</SRS>
+      <SRS>EPSG:32042</SRS>
+      <SRS>EPSG:32043</SRS>
+      <SRS>EPSG:32044</SRS>
+      <SRS>EPSG:32045</SRS>
+      <SRS>EPSG:32046</SRS>
+      <SRS>EPSG:32047</SRS>
+      <SRS>EPSG:32048</SRS>
+      <SRS>EPSG:32049</SRS>
+      <SRS>EPSG:32050</SRS>
+      <SRS>EPSG:32051</SRS>
+      <SRS>EPSG:32052</SRS>
+      <SRS>EPSG:32053</SRS>
+      <SRS>EPSG:32054</SRS>
+      <SRS>EPSG:32055</SRS>
+      <SRS>EPSG:32056</SRS>
+      <SRS>EPSG:32057</SRS>
+      <SRS>EPSG:32058</SRS>
+      <SRS>EPSG:32061</SRS>
+      <SRS>EPSG:32062</SRS>
+      <SRS>EPSG:32064</SRS>
+      <SRS>EPSG:32065</SRS>
+      <SRS>EPSG:32066</SRS>
+      <SRS>EPSG:32067</SRS>
+      <SRS>EPSG:32074</SRS>
+      <SRS>EPSG:32075</SRS>
+      <SRS>EPSG:32076</SRS>
+      <SRS>EPSG:32077</SRS>
+      <SRS>EPSG:32081</SRS>
+      <SRS>EPSG:32082</SRS>
+      <SRS>EPSG:32083</SRS>
+      <SRS>EPSG:32084</SRS>
+      <SRS>EPSG:32085</SRS>
+      <SRS>EPSG:32086</SRS>
+      <SRS>EPSG:32098</SRS>
+      <SRS>EPSG:32099</SRS>
+      <SRS>EPSG:32100</SRS>
+      <SRS>EPSG:32104</SRS>
+      <SRS>EPSG:32107</SRS>
+      <SRS>EPSG:32108</SRS>
+      <SRS>EPSG:32109</SRS>
+      <SRS>EPSG:32110</SRS>
+      <SRS>EPSG:32111</SRS>
+      <SRS>EPSG:32112</SRS>
+      <SRS>EPSG:32113</SRS>
+      <SRS>EPSG:32114</SRS>
+      <SRS>EPSG:32115</SRS>
+      <SRS>EPSG:32116</SRS>
+      <SRS>EPSG:32117</SRS>
+      <SRS>EPSG:32118</SRS>
+      <SRS>EPSG:32119</SRS>
+      <SRS>EPSG:32120</SRS>
+      <SRS>EPSG:32121</SRS>
+      <SRS>EPSG:32122</SRS>
+      <SRS>EPSG:32123</SRS>
+      <SRS>EPSG:32124</SRS>
+      <SRS>EPSG:32125</SRS>
+      <SRS>EPSG:32126</SRS>
+      <SRS>EPSG:32127</SRS>
+      <SRS>EPSG:32128</SRS>
+      <SRS>EPSG:32129</SRS>
+      <SRS>EPSG:32130</SRS>
+      <SRS>EPSG:32133</SRS>
+      <SRS>EPSG:32134</SRS>
+      <SRS>EPSG:32135</SRS>
+      <SRS>EPSG:32136</SRS>
+      <SRS>EPSG:32137</SRS>
+      <SRS>EPSG:32138</SRS>
+      <SRS>EPSG:32139</SRS>
+      <SRS>EPSG:32140</SRS>
+      <SRS>EPSG:32141</SRS>
+      <SRS>EPSG:32142</SRS>
+      <SRS>EPSG:32143</SRS>
+      <SRS>EPSG:32144</SRS>
+      <SRS>EPSG:32145</SRS>
+      <SRS>EPSG:32146</SRS>
+      <SRS>EPSG:32147</SRS>
+      <SRS>EPSG:32148</SRS>
+      <SRS>EPSG:32149</SRS>
+      <SRS>EPSG:32150</SRS>
+      <SRS>EPSG:32151</SRS>
+      <SRS>EPSG:32152</SRS>
+      <SRS>EPSG:32153</SRS>
+      <SRS>EPSG:32154</SRS>
+      <SRS>EPSG:32155</SRS>
+      <SRS>EPSG:32156</SRS>
+      <SRS>EPSG:32157</SRS>
+      <SRS>EPSG:32158</SRS>
+      <SRS>EPSG:32161</SRS>
+      <SRS>EPSG:32164</SRS>
+      <SRS>EPSG:32165</SRS>
+      <SRS>EPSG:32166</SRS>
+      <SRS>EPSG:32167</SRS>
+      <SRS>EPSG:32180</SRS>
+      <SRS>EPSG:32181</SRS>
+      <SRS>EPSG:32182</SRS>
+      <SRS>EPSG:32183</SRS>
+      <SRS>EPSG:32184</SRS>
+      <SRS>EPSG:32185</SRS>
+      <SRS>EPSG:32186</SRS>
+      <SRS>EPSG:32187</SRS>
+      <SRS>EPSG:32188</SRS>
+      <SRS>EPSG:32189</SRS>
+      <SRS>EPSG:32190</SRS>
+      <SRS>EPSG:32191</SRS>
+      <SRS>EPSG:32192</SRS>
+      <SRS>EPSG:32193</SRS>
+      <SRS>EPSG:32194</SRS>
+      <SRS>EPSG:32195</SRS>
+      <SRS>EPSG:32196</SRS>
+      <SRS>EPSG:32197</SRS>
+      <SRS>EPSG:32198</SRS>
+      <SRS>EPSG:32199</SRS>
+      <SRS>EPSG:32201</SRS>
+      <SRS>EPSG:32202</SRS>
+      <SRS>EPSG:32203</SRS>
+      <SRS>EPSG:32204</SRS>
+      <SRS>EPSG:32205</SRS>
+      <SRS>EPSG:32206</SRS>
+      <SRS>EPSG:32207</SRS>
+      <SRS>EPSG:32208</SRS>
+      <SRS>EPSG:32209</SRS>
+      <SRS>EPSG:32210</SRS>
+      <SRS>EPSG:32211</SRS>
+      <SRS>EPSG:32212</SRS>
+      <SRS>EPSG:32213</SRS>
+      <SRS>EPSG:32214</SRS>
+      <SRS>EPSG:32215</SRS>
+      <SRS>EPSG:32216</SRS>
+      <SRS>EPSG:32217</SRS>
+      <SRS>EPSG:32218</SRS>
+      <SRS>EPSG:32219</SRS>
+      <SRS>EPSG:32220</SRS>
+      <SRS>EPSG:32221</SRS>
+      <SRS>EPSG:32222</SRS>
+      <SRS>EPSG:32223</SRS>
+      <SRS>EPSG:32224</SRS>
+      <SRS>EPSG:32225</SRS>
+      <SRS>EPSG:32226</SRS>
+      <SRS>EPSG:32227</SRS>
+      <SRS>EPSG:32228</SRS>
+      <SRS>EPSG:32229</SRS>
+      <SRS>EPSG:32230</SRS>
+      <SRS>EPSG:32231</SRS>
+      <SRS>EPSG:32232</SRS>
+      <SRS>EPSG:32233</SRS>
+      <SRS>EPSG:32234</SRS>
+      <SRS>EPSG:32235</SRS>
+      <SRS>EPSG:32236</SRS>
+      <SRS>EPSG:32237</SRS>
+      <SRS>EPSG:32238</SRS>
+      <SRS>EPSG:32239</SRS>
+      <SRS>EPSG:32240</SRS>
+      <SRS>EPSG:32241</SRS>
+      <SRS>EPSG:32242</SRS>
+      <SRS>EPSG:32243</SRS>
+      <SRS>EPSG:32244</SRS>
+      <SRS>EPSG:32245</SRS>
+      <SRS>EPSG:32246</SRS>
+      <SRS>EPSG:32247</SRS>
+      <SRS>EPSG:32248</SRS>
+      <SRS>EPSG:32249</SRS>
+      <SRS>EPSG:32250</SRS>
+      <SRS>EPSG:32251</SRS>
+      <SRS>EPSG:32252</SRS>
+      <SRS>EPSG:32253</SRS>
+      <SRS>EPSG:32254</SRS>
+      <SRS>EPSG:32255</SRS>
+      <SRS>EPSG:32256</SRS>
+      <SRS>EPSG:32257</SRS>
+      <SRS>EPSG:32258</SRS>
+      <SRS>EPSG:32259</SRS>
+      <SRS>EPSG:32260</SRS>
+      <SRS>EPSG:32301</SRS>
+      <SRS>EPSG:32302</SRS>
+      <SRS>EPSG:32303</SRS>
+      <SRS>EPSG:32304</SRS>
+      <SRS>EPSG:32305</SRS>
+      <SRS>EPSG:32306</SRS>
+      <SRS>EPSG:32307</SRS>
+      <SRS>EPSG:32308</SRS>
+      <SRS>EPSG:32309</SRS>
+      <SRS>EPSG:32310</SRS>
+      <SRS>EPSG:32311</SRS>
+      <SRS>EPSG:32312</SRS>
+      <SRS>EPSG:32313</SRS>
+      <SRS>EPSG:32314</SRS>
+      <SRS>EPSG:32315</SRS>
+      <SRS>EPSG:32316</SRS>
+      <SRS>EPSG:32317</SRS>
+      <SRS>EPSG:32318</SRS>
+      <SRS>EPSG:32319</SRS>
+      <SRS>EPSG:32320</SRS>
+      <SRS>EPSG:32321</SRS>
+      <SRS>EPSG:32322</SRS>
+      <SRS>EPSG:32323</SRS>
+      <SRS>EPSG:32324</SRS>
+      <SRS>EPSG:32325</SRS>
+      <SRS>EPSG:32326</SRS>
+      <SRS>EPSG:32327</SRS>
+      <SRS>EPSG:32328</SRS>
+      <SRS>EPSG:32329</SRS>
+      <SRS>EPSG:32330</SRS>
+      <SRS>EPSG:32331</SRS>
+      <SRS>EPSG:32332</SRS>
+      <SRS>EPSG:32333</SRS>
+      <SRS>EPSG:32334</SRS>
+      <SRS>EPSG:32335</SRS>
+      <SRS>EPSG:32336</SRS>
+      <SRS>EPSG:32337</SRS>
+      <SRS>EPSG:32338</SRS>
+      <SRS>EPSG:32339</SRS>
+      <SRS>EPSG:32340</SRS>
+      <SRS>EPSG:32341</SRS>
+      <SRS>EPSG:32342</SRS>
+      <SRS>EPSG:32343</SRS>
+      <SRS>EPSG:32344</SRS>
+      <SRS>EPSG:32345</SRS>
+      <SRS>EPSG:32346</SRS>
+      <SRS>EPSG:32347</SRS>
+      <SRS>EPSG:32348</SRS>
+      <SRS>EPSG:32349</SRS>
+      <SRS>EPSG:32350</SRS>
+      <SRS>EPSG:32351</SRS>
+      <SRS>EPSG:32352</SRS>
+      <SRS>EPSG:32353</SRS>
+      <SRS>EPSG:32354</SRS>
+      <SRS>EPSG:32355</SRS>
+      <SRS>EPSG:32356</SRS>
+      <SRS>EPSG:32357</SRS>
+      <SRS>EPSG:32358</SRS>
+      <SRS>EPSG:32359</SRS>
+      <SRS>EPSG:32360</SRS>
+      <SRS>EPSG:32401</SRS>
+      <SRS>EPSG:32402</SRS>
+      <SRS>EPSG:32403</SRS>
+      <SRS>EPSG:32404</SRS>
+      <SRS>EPSG:32405</SRS>
+      <SRS>EPSG:32406</SRS>
+      <SRS>EPSG:32407</SRS>
+      <SRS>EPSG:32408</SRS>
+      <SRS>EPSG:32409</SRS>
+      <SRS>EPSG:32410</SRS>
+      <SRS>EPSG:32411</SRS>
+      <SRS>EPSG:32412</SRS>
+      <SRS>EPSG:32413</SRS>
+      <SRS>EPSG:32414</SRS>
+      <SRS>EPSG:32415</SRS>
+      <SRS>EPSG:32416</SRS>
+      <SRS>EPSG:32417</SRS>
+      <SRS>EPSG:32418</SRS>
+      <SRS>EPSG:32419</SRS>
+      <SRS>EPSG:32420</SRS>
+      <SRS>EPSG:32421</SRS>
+      <SRS>EPSG:32422</SRS>
+      <SRS>EPSG:32423</SRS>
+      <SRS>EPSG:32424</SRS>
+      <SRS>EPSG:32425</SRS>
+      <SRS>EPSG:32426</SRS>
+      <SRS>EPSG:32427</SRS>
+      <SRS>EPSG:32428</SRS>
+      <SRS>EPSG:32429</SRS>
+      <SRS>EPSG:32430</SRS>
+      <SRS>EPSG:32431</SRS>
+      <SRS>EPSG:32432</SRS>
+      <SRS>EPSG:32433</SRS>
+      <SRS>EPSG:32434</SRS>
+      <SRS>EPSG:32435</SRS>
+      <SRS>EPSG:32436</SRS>
+      <SRS>EPSG:32437</SRS>
+      <SRS>EPSG:32438</SRS>
+      <SRS>EPSG:32439</SRS>
+      <SRS>EPSG:32440</SRS>
+      <SRS>EPSG:32441</SRS>
+      <SRS>EPSG:32442</SRS>
+      <SRS>EPSG:32443</SRS>
+      <SRS>EPSG:32444</SRS>
+      <SRS>EPSG:32445</SRS>
+      <SRS>EPSG:32446</SRS>
+      <SRS>EPSG:32447</SRS>
+      <SRS>EPSG:32448</SRS>
+      <SRS>EPSG:32449</SRS>
+      <SRS>EPSG:32450</SRS>
+      <SRS>EPSG:32451</SRS>
+      <SRS>EPSG:32452</SRS>
+      <SRS>EPSG:32453</SRS>
+      <SRS>EPSG:32454</SRS>
+      <SRS>EPSG:32455</SRS>
+      <SRS>EPSG:32456</SRS>
+      <SRS>EPSG:32457</SRS>
+      <SRS>EPSG:32458</SRS>
+      <SRS>EPSG:32459</SRS>
+      <SRS>EPSG:32460</SRS>
+      <SRS>EPSG:32501</SRS>
+      <SRS>EPSG:32502</SRS>
+      <SRS>EPSG:32503</SRS>
+      <SRS>EPSG:32504</SRS>
+      <SRS>EPSG:32505</SRS>
+      <SRS>EPSG:32506</SRS>
+      <SRS>EPSG:32507</SRS>
+      <SRS>EPSG:32508</SRS>
+      <SRS>EPSG:32509</SRS>
+      <SRS>EPSG:32510</SRS>
+      <SRS>EPSG:32511</SRS>
+      <SRS>EPSG:32512</SRS>
+      <SRS>EPSG:32513</SRS>
+      <SRS>EPSG:32514</SRS>
+      <SRS>EPSG:32515</SRS>
+      <SRS>EPSG:32516</SRS>
+      <SRS>EPSG:32517</SRS>
+      <SRS>EPSG:32518</SRS>
+      <SRS>EPSG:32519</SRS>
+      <SRS>EPSG:32520</SRS>
+      <SRS>EPSG:32521</SRS>
+      <SRS>EPSG:32522</SRS>
+      <SRS>EPSG:32523</SRS>
+      <SRS>EPSG:32524</SRS>
+      <SRS>EPSG:32525</SRS>
+      <SRS>EPSG:32526</SRS>
+      <SRS>EPSG:32527</SRS>
+      <SRS>EPSG:32528</SRS>
+      <SRS>EPSG:32529</SRS>
+      <SRS>EPSG:32530</SRS>
+      <SRS>EPSG:32531</SRS>
+      <SRS>EPSG:32532</SRS>
+      <SRS>EPSG:32533</SRS>
+      <SRS>EPSG:32534</SRS>
+      <SRS>EPSG:32535</SRS>
+      <SRS>EPSG:32536</SRS>
+      <SRS>EPSG:32537</SRS>
+      <SRS>EPSG:32538</SRS>
+      <SRS>EPSG:32539</SRS>
+      <SRS>EPSG:32540</SRS>
+      <SRS>EPSG:32541</SRS>
+      <SRS>EPSG:32542</SRS>
+      <SRS>EPSG:32543</SRS>
+      <SRS>EPSG:32544</SRS>
+      <SRS>EPSG:32545</SRS>
+      <SRS>EPSG:32546</SRS>
+      <SRS>EPSG:32547</SRS>
+      <SRS>EPSG:32548</SRS>
+      <SRS>EPSG:32549</SRS>
+      <SRS>EPSG:32550</SRS>
+      <SRS>EPSG:32551</SRS>
+      <SRS>EPSG:32552</SRS>
+      <SRS>EPSG:32553</SRS>
+      <SRS>EPSG:32554</SRS>
+      <SRS>EPSG:32555</SRS>
+      <SRS>EPSG:32556</SRS>
+      <SRS>EPSG:32557</SRS>
+      <SRS>EPSG:32558</SRS>
+      <SRS>EPSG:32559</SRS>
+      <SRS>EPSG:32560</SRS>
+      <SRS>EPSG:32600</SRS>
+      <SRS>EPSG:32601</SRS>
+      <SRS>EPSG:32602</SRS>
+      <SRS>EPSG:32603</SRS>
+      <SRS>EPSG:32604</SRS>
+      <SRS>EPSG:32605</SRS>
+      <SRS>EPSG:32606</SRS>
+      <SRS>EPSG:32607</SRS>
+      <SRS>EPSG:32608</SRS>
+      <SRS>EPSG:32609</SRS>
+      <SRS>EPSG:32610</SRS>
+      <SRS>EPSG:32611</SRS>
+      <SRS>EPSG:32612</SRS>
+      <SRS>EPSG:32613</SRS>
+      <SRS>EPSG:32614</SRS>
+      <SRS>EPSG:32615</SRS>
+      <SRS>EPSG:32616</SRS>
+      <SRS>EPSG:32617</SRS>
+      <SRS>EPSG:32618</SRS>
+      <SRS>EPSG:32619</SRS>
+      <SRS>EPSG:32620</SRS>
+      <SRS>EPSG:32621</SRS>
+      <SRS>EPSG:32622</SRS>
+      <SRS>EPSG:32623</SRS>
+      <SRS>EPSG:32624</SRS>
+      <SRS>EPSG:32625</SRS>
+      <SRS>EPSG:32626</SRS>
+      <SRS>EPSG:32627</SRS>
+      <SRS>EPSG:32628</SRS>
+      <SRS>EPSG:32629</SRS>
+      <SRS>EPSG:32630</SRS>
+      <SRS>EPSG:32631</SRS>
+      <SRS>EPSG:32632</SRS>
+      <SRS>EPSG:32633</SRS>
+      <SRS>EPSG:32634</SRS>
+      <SRS>EPSG:32635</SRS>
+      <SRS>EPSG:32636</SRS>
+      <SRS>EPSG:32637</SRS>
+      <SRS>EPSG:32638</SRS>
+      <SRS>EPSG:32639</SRS>
+      <SRS>EPSG:32640</SRS>
+      <SRS>EPSG:32641</SRS>
+      <SRS>EPSG:32642</SRS>
+      <SRS>EPSG:32643</SRS>
+      <SRS>EPSG:32644</SRS>
+      <SRS>EPSG:32645</SRS>
+      <SRS>EPSG:32646</SRS>
+      <SRS>EPSG:32647</SRS>
+      <SRS>EPSG:32648</SRS>
+      <SRS>EPSG:32649</SRS>
+      <SRS>EPSG:32650</SRS>
+      <SRS>EPSG:32651</SRS>
+      <SRS>EPSG:32652</SRS>
+      <SRS>EPSG:32653</SRS>
+      <SRS>EPSG:32654</SRS>
+      <SRS>EPSG:32655</SRS>
+      <SRS>EPSG:32656</SRS>
+      <SRS>EPSG:32657</SRS>
+      <SRS>EPSG:32658</SRS>
+      <SRS>EPSG:32659</SRS>
+      <SRS>EPSG:32660</SRS>
+      <SRS>EPSG:32661</SRS>
+      <SRS>EPSG:32662</SRS>
+      <SRS>EPSG:32664</SRS>
+      <SRS>EPSG:32665</SRS>
+      <SRS>EPSG:32666</SRS>
+      <SRS>EPSG:32667</SRS>
+      <SRS>EPSG:32700</SRS>
+      <SRS>EPSG:32701</SRS>
+      <SRS>EPSG:32702</SRS>
+      <SRS>EPSG:32703</SRS>
+      <SRS>EPSG:32704</SRS>
+      <SRS>EPSG:32705</SRS>
+      <SRS>EPSG:32706</SRS>
+      <SRS>EPSG:32707</SRS>
+      <SRS>EPSG:32708</SRS>
+      <SRS>EPSG:32709</SRS>
+      <SRS>EPSG:32710</SRS>
+      <SRS>EPSG:32711</SRS>
+      <SRS>EPSG:32712</SRS>
+      <SRS>EPSG:32713</SRS>
+      <SRS>EPSG:32714</SRS>
+      <SRS>EPSG:32715</SRS>
+      <SRS>EPSG:32716</SRS>
+      <SRS>EPSG:32717</SRS>
+      <SRS>EPSG:32718</SRS>
+      <SRS>EPSG:32719</SRS>
+      <SRS>EPSG:32720</SRS>
+      <SRS>EPSG:32721</SRS>
+      <SRS>EPSG:32722</SRS>
+      <SRS>EPSG:32723</SRS>
+      <SRS>EPSG:32724</SRS>
+      <SRS>EPSG:32725</SRS>
+      <SRS>EPSG:32726</SRS>
+      <SRS>EPSG:32727</SRS>
+      <SRS>EPSG:32728</SRS>
+      <SRS>EPSG:32729</SRS>
+      <SRS>EPSG:32730</SRS>
+      <SRS>EPSG:32731</SRS>
+      <SRS>EPSG:32732</SRS>
+      <SRS>EPSG:32733</SRS>
+      <SRS>EPSG:32734</SRS>
+      <SRS>EPSG:32735</SRS>
+      <SRS>EPSG:32736</SRS>
+      <SRS>EPSG:32737</SRS>
+      <SRS>EPSG:32738</SRS>
+      <SRS>EPSG:32739</SRS>
+      <SRS>EPSG:32740</SRS>
+      <SRS>EPSG:32741</SRS>
+      <SRS>EPSG:32742</SRS>
+      <SRS>EPSG:32743</SRS>
+      <SRS>EPSG:32744</SRS>
+      <SRS>EPSG:32745</SRS>
+      <SRS>EPSG:32746</SRS>
+      <SRS>EPSG:32747</SRS>
+      <SRS>EPSG:32748</SRS>
+      <SRS>EPSG:32749</SRS>
+      <SRS>EPSG:32750</SRS>
+      <SRS>EPSG:32751</SRS>
+      <SRS>EPSG:32752</SRS>
+      <SRS>EPSG:32753</SRS>
+      <SRS>EPSG:32754</SRS>
+      <SRS>EPSG:32755</SRS>
+      <SRS>EPSG:32756</SRS>
+      <SRS>EPSG:32757</SRS>
+      <SRS>EPSG:32758</SRS>
+      <SRS>EPSG:32759</SRS>
+      <SRS>EPSG:32760</SRS>
+      <SRS>EPSG:32761</SRS>
+      <SRS>EPSG:32766</SRS>
+      <SRS>EPSG:61206405</SRS>
+      <SRS>EPSG:61216405</SRS>
+      <SRS>EPSG:61226405</SRS>
+      <SRS>EPSG:61236405</SRS>
+      <SRS>EPSG:61246405</SRS>
+      <SRS>EPSG:61266405</SRS>
+      <SRS>EPSG:61266413</SRS>
+      <SRS>EPSG:61276405</SRS>
+      <SRS>EPSG:61286405</SRS>
+      <SRS>EPSG:61296405</SRS>
+      <SRS>EPSG:61306405</SRS>
+      <SRS>EPSG:61306413</SRS>
+      <SRS>EPSG:61316405</SRS>
+      <SRS>EPSG:61326405</SRS>
+      <SRS>EPSG:61336405</SRS>
+      <SRS>EPSG:61346405</SRS>
+      <SRS>EPSG:61356405</SRS>
+      <SRS>EPSG:61366405</SRS>
+      <SRS>EPSG:61376405</SRS>
+      <SRS>EPSG:61386405</SRS>
+      <SRS>EPSG:61396405</SRS>
+      <SRS>EPSG:61406405</SRS>
+      <SRS>EPSG:61406413</SRS>
+      <SRS>EPSG:61416405</SRS>
+      <SRS>EPSG:61426405</SRS>
+      <SRS>EPSG:61436405</SRS>
+      <SRS>EPSG:61446405</SRS>
+      <SRS>EPSG:61456405</SRS>
+      <SRS>EPSG:61466405</SRS>
+      <SRS>EPSG:61476405</SRS>
+      <SRS>EPSG:61486405</SRS>
+      <SRS>EPSG:61486413</SRS>
+      <SRS>EPSG:61496405</SRS>
+      <SRS>EPSG:61506405</SRS>
+      <SRS>EPSG:61516405</SRS>
+      <SRS>EPSG:61516413</SRS>
+      <SRS>EPSG:61526405</SRS>
+      <SRS>EPSG:61526413</SRS>
+      <SRS>EPSG:61536405</SRS>
+      <SRS>EPSG:61546405</SRS>
+      <SRS>EPSG:61556405</SRS>
+      <SRS>EPSG:61566405</SRS>
+      <SRS>EPSG:61576405</SRS>
+      <SRS>EPSG:61586405</SRS>
+      <SRS>EPSG:61596405</SRS>
+      <SRS>EPSG:61606405</SRS>
+      <SRS>EPSG:61616405</SRS>
+      <SRS>EPSG:61626405</SRS>
+      <SRS>EPSG:61636405</SRS>
+      <SRS>EPSG:61636413</SRS>
+      <SRS>EPSG:61646405</SRS>
+      <SRS>EPSG:61656405</SRS>
+      <SRS>EPSG:61666405</SRS>
+      <SRS>EPSG:61676405</SRS>
+      <SRS>EPSG:61676413</SRS>
+      <SRS>EPSG:61686405</SRS>
+      <SRS>EPSG:61696405</SRS>
+      <SRS>EPSG:61706405</SRS>
+      <SRS>EPSG:61706413</SRS>
+      <SRS>EPSG:61716405</SRS>
+      <SRS>EPSG:61716413</SRS>
+      <SRS>EPSG:61736405</SRS>
+      <SRS>EPSG:61736413</SRS>
+      <SRS>EPSG:61746405</SRS>
+      <SRS>EPSG:61756405</SRS>
+      <SRS>EPSG:61766405</SRS>
+      <SRS>EPSG:61766413</SRS>
+      <SRS>EPSG:61786405</SRS>
+      <SRS>EPSG:61796405</SRS>
+      <SRS>EPSG:61806405</SRS>
+      <SRS>EPSG:61806413</SRS>
+      <SRS>EPSG:61816405</SRS>
+      <SRS>EPSG:61826405</SRS>
+      <SRS>EPSG:61836405</SRS>
+      <SRS>EPSG:61846405</SRS>
+      <SRS>EPSG:61886405</SRS>
+      <SRS>EPSG:61896405</SRS>
+      <SRS>EPSG:61896413</SRS>
+      <SRS>EPSG:61906405</SRS>
+      <SRS>EPSG:61906413</SRS>
+      <SRS>EPSG:61916405</SRS>
+      <SRS>EPSG:61926405</SRS>
+      <SRS>EPSG:61936405</SRS>
+      <SRS>EPSG:61946405</SRS>
+      <SRS>EPSG:61956405</SRS>
+      <SRS>EPSG:61966405</SRS>
+      <SRS>EPSG:61976405</SRS>
+      <SRS>EPSG:61986405</SRS>
+      <SRS>EPSG:61996405</SRS>
+      <SRS>EPSG:62006405</SRS>
+      <SRS>EPSG:62016405</SRS>
+      <SRS>EPSG:62026405</SRS>
+      <SRS>EPSG:62036405</SRS>
+      <SRS>EPSG:62046405</SRS>
+      <SRS>EPSG:62056405</SRS>
+      <SRS>EPSG:62066405</SRS>
+      <SRS>EPSG:62076405</SRS>
+      <SRS>EPSG:62086405</SRS>
+      <SRS>EPSG:62096405</SRS>
+      <SRS>EPSG:62106405</SRS>
+      <SRS>EPSG:62116405</SRS>
+      <SRS>EPSG:62126405</SRS>
+      <SRS>EPSG:62136405</SRS>
+      <SRS>EPSG:62146405</SRS>
+      <SRS>EPSG:62156405</SRS>
+      <SRS>EPSG:62166405</SRS>
+      <SRS>EPSG:62186405</SRS>
+      <SRS>EPSG:62196405</SRS>
+      <SRS>EPSG:62206405</SRS>
+      <SRS>EPSG:62216405</SRS>
+      <SRS>EPSG:62226405</SRS>
+      <SRS>EPSG:62236405</SRS>
+      <SRS>EPSG:62246405</SRS>
+      <SRS>EPSG:62256405</SRS>
+      <SRS>EPSG:62276405</SRS>
+      <SRS>EPSG:62296405</SRS>
+      <SRS>EPSG:62306405</SRS>
+      <SRS>EPSG:62316405</SRS>
+      <SRS>EPSG:62326405</SRS>
+      <SRS>EPSG:62336405</SRS>
+      <SRS>EPSG:62366405</SRS>
+      <SRS>EPSG:62376405</SRS>
+      <SRS>EPSG:62386405</SRS>
+      <SRS>EPSG:62396405</SRS>
+      <SRS>EPSG:62406405</SRS>
+      <SRS>EPSG:62416405</SRS>
+      <SRS>EPSG:62426405</SRS>
+      <SRS>EPSG:62436405</SRS>
+      <SRS>EPSG:62446405</SRS>
+      <SRS>EPSG:62456405</SRS>
+      <SRS>EPSG:62466405</SRS>
+      <SRS>EPSG:62476405</SRS>
+      <SRS>EPSG:62486405</SRS>
+      <SRS>EPSG:62496405</SRS>
+      <SRS>EPSG:62506405</SRS>
+      <SRS>EPSG:62516405</SRS>
+      <SRS>EPSG:62526405</SRS>
+      <SRS>EPSG:62536405</SRS>
+      <SRS>EPSG:62546405</SRS>
+      <SRS>EPSG:62556405</SRS>
+      <SRS>EPSG:62566405</SRS>
+      <SRS>EPSG:62576405</SRS>
+      <SRS>EPSG:62586405</SRS>
+      <SRS>EPSG:62586413</SRS>
+      <SRS>EPSG:62596405</SRS>
+      <SRS>EPSG:62616405</SRS>
+      <SRS>EPSG:62626405</SRS>
+      <SRS>EPSG:62636405</SRS>
+      <SRS>EPSG:62646405</SRS>
+      <SRS>EPSG:62656405</SRS>
+      <SRS>EPSG:62666405</SRS>
+      <SRS>EPSG:62676405</SRS>
+      <SRS>EPSG:62686405</SRS>
+      <SRS>EPSG:62696405</SRS>
+      <SRS>EPSG:62706405</SRS>
+      <SRS>EPSG:62716405</SRS>
+      <SRS>EPSG:62726405</SRS>
+      <SRS>EPSG:62736405</SRS>
+      <SRS>EPSG:62746405</SRS>
+      <SRS>EPSG:62756405</SRS>
+      <SRS>EPSG:62766405</SRS>
+      <SRS>EPSG:62776405</SRS>
+      <SRS>EPSG:62786405</SRS>
+      <SRS>EPSG:62796405</SRS>
+      <SRS>EPSG:62806405</SRS>
+      <SRS>EPSG:62816405</SRS>
+      <SRS>EPSG:62826405</SRS>
+      <SRS>EPSG:62836405</SRS>
+      <SRS>EPSG:62836413</SRS>
+      <SRS>EPSG:62846405</SRS>
+      <SRS>EPSG:62856405</SRS>
+      <SRS>EPSG:62866405</SRS>
+      <SRS>EPSG:62886405</SRS>
+      <SRS>EPSG:62896405</SRS>
+      <SRS>EPSG:62926405</SRS>
+      <SRS>EPSG:62936405</SRS>
+      <SRS>EPSG:62956405</SRS>
+      <SRS>EPSG:62976405</SRS>
+      <SRS>EPSG:62986405</SRS>
+      <SRS>EPSG:62996405</SRS>
+      <SRS>EPSG:63006405</SRS>
+      <SRS>EPSG:63016405</SRS>
+      <SRS>EPSG:63026405</SRS>
+      <SRS>EPSG:63036405</SRS>
+      <SRS>EPSG:63046405</SRS>
+      <SRS>EPSG:63066405</SRS>
+      <SRS>EPSG:63076405</SRS>
+      <SRS>EPSG:63086405</SRS>
+      <SRS>EPSG:63096405</SRS>
+      <SRS>EPSG:63106405</SRS>
+      <SRS>EPSG:63116405</SRS>
+      <SRS>EPSG:63126405</SRS>
+      <SRS>EPSG:63136405</SRS>
+      <SRS>EPSG:63146405</SRS>
+      <SRS>EPSG:63156405</SRS>
+      <SRS>EPSG:63166405</SRS>
+      <SRS>EPSG:63176405</SRS>
+      <SRS>EPSG:63186405</SRS>
+      <SRS>EPSG:63196405</SRS>
+      <SRS>EPSG:63226405</SRS>
+      <SRS>EPSG:63246405</SRS>
+      <SRS>EPSG:63266405</SRS>
+      <SRS>EPSG:63266406</SRS>
+      <SRS>EPSG:63266407</SRS>
+      <SRS>EPSG:63266408</SRS>
+      <SRS>EPSG:63266409</SRS>
+      <SRS>EPSG:63266410</SRS>
+      <SRS>EPSG:63266411</SRS>
+      <SRS>EPSG:63266412</SRS>
+      <SRS>EPSG:63266413</SRS>
+      <SRS>EPSG:63266414</SRS>
+      <SRS>EPSG:63266415</SRS>
+      <SRS>EPSG:63266416</SRS>
+      <SRS>EPSG:63266417</SRS>
+      <SRS>EPSG:63266418</SRS>
+      <SRS>EPSG:63266419</SRS>
+      <SRS>EPSG:63266420</SRS>
+      <SRS>EPSG:66006405</SRS>
+      <SRS>EPSG:66016405</SRS>
+      <SRS>EPSG:66026405</SRS>
+      <SRS>EPSG:66036405</SRS>
+      <SRS>EPSG:66046405</SRS>
+      <SRS>EPSG:66056405</SRS>
+      <SRS>EPSG:66066405</SRS>
+      <SRS>EPSG:66076405</SRS>
+      <SRS>EPSG:66086405</SRS>
+      <SRS>EPSG:66096405</SRS>
+      <SRS>EPSG:66106405</SRS>
+      <SRS>EPSG:66116405</SRS>
+      <SRS>EPSG:66126405</SRS>
+      <SRS>EPSG:66126413</SRS>
+      <SRS>EPSG:66136405</SRS>
+      <SRS>EPSG:66146405</SRS>
+      <SRS>EPSG:66156405</SRS>
+      <SRS>EPSG:66166405</SRS>
+      <SRS>EPSG:66186405</SRS>
+      <SRS>EPSG:66196405</SRS>
+      <SRS>EPSG:66196413</SRS>
+      <SRS>EPSG:66206405</SRS>
+      <SRS>EPSG:66216405</SRS>
+      <SRS>EPSG:66226405</SRS>
+      <SRS>EPSG:66236405</SRS>
+      <SRS>EPSG:66246405</SRS>
+      <SRS>EPSG:66246413</SRS>
+      <SRS>EPSG:66256405</SRS>
+      <SRS>EPSG:66266405</SRS>
+      <SRS>EPSG:66276405</SRS>
+      <SRS>EPSG:66276413</SRS>
+      <SRS>EPSG:66286405</SRS>
+      <SRS>EPSG:66296405</SRS>
+      <SRS>EPSG:66306405</SRS>
+      <SRS>EPSG:66316405</SRS>
+      <SRS>EPSG:66326405</SRS>
+      <SRS>EPSG:66336405</SRS>
+      <SRS>EPSG:66346405</SRS>
+      <SRS>EPSG:66356405</SRS>
+      <SRS>EPSG:66366405</SRS>
+      <SRS>EPSG:66376405</SRS>
+      <SRS>EPSG:66386405</SRS>
+      <SRS>EPSG:66396405</SRS>
+      <SRS>EPSG:66406405</SRS>
+      <SRS>EPSG:66406413</SRS>
+      <SRS>EPSG:66416405</SRS>
+      <SRS>EPSG:66426405</SRS>
+      <SRS>EPSG:66436405</SRS>
+      <SRS>EPSG:66446405</SRS>
+      <SRS>EPSG:66456405</SRS>
+      <SRS>EPSG:66456413</SRS>
+      <SRS>EPSG:66466405</SRS>
+      <SRS>EPSG:66576405</SRS>
+      <SRS>EPSG:66586405</SRS>
+      <SRS>EPSG:66596405</SRS>
+      <SRS>EPSG:66596413</SRS>
+      <SRS>EPSG:66606405</SRS>
+      <SRS>EPSG:66616405</SRS>
+      <SRS>EPSG:66616413</SRS>
+      <SRS>EPSG:66636405</SRS>
+      <SRS>EPSG:66646405</SRS>
+      <SRS>EPSG:66656405</SRS>
+      <SRS>EPSG:66666405</SRS>
+      <SRS>EPSG:66676405</SRS>
+      <SRS>EPSG:68016405</SRS>
+      <SRS>EPSG:68026405</SRS>
+      <SRS>EPSG:68036405</SRS>
+      <SRS>EPSG:68046405</SRS>
+      <SRS>EPSG:68056405</SRS>
+      <SRS>EPSG:68066405</SRS>
+      <SRS>EPSG:68086405</SRS>
+      <SRS>EPSG:68096405</SRS>
+      <SRS>EPSG:68136405</SRS>
+      <SRS>EPSG:68146405</SRS>
+      <SRS>EPSG:68156405</SRS>
+      <SRS>EPSG:68186405</SRS>
+      <SRS>EPSG:68206405</SRS>
+      <SRS>EPSG:69036405</SRS>
+      <SRS>EPSG:42302</SRS>
+      <SRS>EPSG:42301</SRS>
+      <SRS>EPSG:900913</SRS>
+      <SRS>EPSG:45556</SRS>
+      <SRS>EPSG:45555</SRS>
+      <SRS>EPSG:54004</SRS>
+      <SRS>EPSG:41001</SRS>
+      <SRS>EPSG:42311</SRS>
+      <SRS>EPSG:42310</SRS>
+      <SRS>EPSG:18001</SRS>
+      <SRS>EPSG:100003</SRS>
+      <SRS>EPSG:42106</SRS>
+      <SRS>EPSG:100002</SRS>
+      <SRS>EPSG:42105</SRS>
+      <SRS>EPSG:100001</SRS>
+      <SRS>EPSG:42309</SRS>
+      <SRS>EPSG:42104</SRS>
+      <SRS>EPSG:42308</SRS>
+      <SRS>EPSG:42103</SRS>
+      <SRS>EPSG:42307</SRS>
+      <SRS>EPSG:42102</SRS>
+      <SRS>EPSG:42306</SRS>
+      <SRS>EPSG:42101</SRS>
+      <SRS>EPSG:42305</SRS>
+      <SRS>EPSG:42304</SRS>
+      <SRS>EPSG:42303</SRS>
+      <LatLonBoundingBox minx="-257.0843245637291" miny="-257.0843245637291" maxx="257.0843245637291" maxy="257.0843245637291"/>
+      <Layer queryable="1">
+        <Name>tiger:poly_landmarks</Name>
+        <Title>Manhattan (NY) landmarks</Title>
+        <Abstract>Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs</Abstract>
+        <KeywordList>
+          <Keyword>DS_poly_landmarks</Keyword>
+          <Keyword>poly_landmarks</Keyword>
+          <Keyword>landmarks</Keyword>
+          <Keyword>manhattan</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-74.1008830202198" miny="40.65748247978021" maxx="-73.8541219797802" maxy="40.90424352021979"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.90782" maxy="40.882078"/>
+        <Style>
+          <Name>poly_landmarks</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poly_landmarks"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:poi</Name>
+        <Title>Manhattan (NY) points of interest</Title>
+        <Abstract>Points of interest in New York, New York (on Manhattan). One of the attributes contains the name of a file with a picture of the point of interest.</Abstract>
+        <KeywordList>
+          <Keyword>poi</Keyword>
+          <Keyword>DS_poi</Keyword>
+          <Keyword>points_of_interest</Keyword>
+          <Keyword>Manhattan</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-74.01288357289539" miny="40.70706518152972" maxx="-74.00752144792617" maxy="40.71242730649893"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.0118315772888" miny="40.70754683896324" maxx="-74.00153046439813" maxy="40.719885123828675"/>
+        <Style>
+          <Name>poi</Name>
+          <Title>Points of interest</Title>
+          <Abstract>Manhattan points of interest</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poi"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:tiger_roads</Name>
+        <Title>Manhattan (NY) roads</Title>
+        <Abstract>Highly simplified road layout of Manhattan in New York..</Abstract>
+        <KeywordList>
+          <Keyword>DS_tiger_roads</Keyword>
+          <Keyword>tiger_roads</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-74.08769307536667" miny="40.660618924633326" maxx="-73.84653192463333" maxy="40.90178007536667"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.02722" miny="40.684221" maxx="-73.907005" maxy="40.878178"/>
+        <Style>
+          <Name>tiger_roads</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:tiger_roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:archsites</Name>
+        <Title>Spearfish archeological sites</Title>
+        <Abstract>Sample data from GRASS, archeological sites location, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>archsites</Keyword>
+          <Keyword>sfArchsites</Keyword>
+          <Keyword>spearfish</Keyword>
+          <Keyword>archeology</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.89000625326194" miny="44.29796961116877" maxx="-103.62049935931161" maxy="44.5674765051191"/>
+        <BoundingBox SRS="EPSG:26713" minx="588926.6865343997" miny="4913890.332215005" maxx="609271.2114429093" maxy="4927102.448786693"/>
+        <Style>
+          <Name>point</Name>
+          <Title>Default point</Title>
+          <Abstract>A sample style that just prints out a 6px wide red square</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:archsites"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:bugsites</Name>
+        <Title>Spearfish bug locations</Title>
+        <Abstract>Sample data from GRASS, bug sites location, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>sfBugsites</Keyword>
+          <Keyword>bugsites</Keyword>
+          <Keyword>insects</Keyword>
+          <Keyword>spearfish</Keyword>
+          <Keyword>tiger_beetles</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.89041901614995" miny="44.266492773791775" maxx="-103.61527753322848" maxy="44.54163425671326"/>
+        <BoundingBox SRS="EPSG:26713" minx="589311.4871629482" miny="4913787.082099182" maxx="609374.4115724327" maxy="4920844.691225147"/>
+        <Style>
+          <Name>capitals</Name>
+          <Title>Capital cities</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:bugsites"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:restricted</Name>
+        <Title>Spearfish restricted areas</Title>
+        <Abstract>Sample data from GRASS, restricted areas, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>restricted</Keyword>
+          <Keyword>sfRestricted</Keyword>
+          <Keyword>spearfish</Keyword>
+          <Keyword>areas</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.86063428986338" miny="44.37661974734028" maxx="-103.73735238788223" maxy="44.49990164932145"/>
+        <BoundingBox SRS="EPSG:26713" minx="591175.6988413236" miny="4915754.888027622" maxx="600052.4121365736" maxy="4926353.920417598"/>
+        <Style>
+          <Name>restricted</Name>
+          <Title>Red, translucent style</Title>
+          <Abstract>A sample style that just prints out a transparent red interior with a red outline</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:restricted"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:roads</Name>
+        <Title>Spearfish roads</Title>
+        <Abstract>Sample data from GRASS, road layout, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>sfRoads</Keyword>
+          <Keyword>roads</Keyword>
+          <Keyword>spearfish</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.90534996703491" miny="44.2800314829381" maxx="-103.5943809967035" maxy="44.5910004532695"/>
+        <BoundingBox SRS="EPSG:26713" minx="588430.2387813567" miny="4913303.484828213" maxx="610531.8279023392" maxy="4928766.251023613"/>
+        <Style>
+          <Name>simple_roads</Name>
+          <Title>Default Styler for simple road segments</Title>
+          <Abstract>Light red line, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:streams</Name>
+        <Title>Spearfish streams</Title>
+        <Abstract>Sample data from GRASS, streams, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>sfStreams</Keyword>
+          <Keyword>streams</Keyword>
+          <Keyword>spearfish</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.9089219204826" miny="44.278738996398694" maxx="-103.59184616696963" maxy="44.595814749911675"/>
+        <BoundingBox SRS="EPSG:26713" minx="588430.3113926318" miny="4913241.156915463" maxx="610522.3974737043" maxy="4928777.235349244"/>
+        <Style>
+          <Name>simple_streams</Name>
+          <Title>Default Styler for streams segments</Title>
+          <Abstract>Blue lines, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:streams"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_cities</Name>
+        <Title>Tasmania cities</Title>
+        <Abstract>Cities in Tasmania (actually, just the capital)</Abstract>
+        <KeywordList>
+          <Keyword>cities</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="144.93357593664516" miny="-43.93984106335484" maxx="148.53694406335487" maxy="-40.33647293664516"/>
+        <BoundingBox SRS="EPSG:4326" minx="147.2910004483" miny="-42.851001816890005" maxx="147.2910004483" maxy="-42.851001816890005"/>
+        <Style>
+          <Name>capitals</Name>
+          <Title>Capital cities</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_cities"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_roads</Name>
+        <Title>Tasmania roads</Title>
+        <Abstract>Main Tasmania roads</Abstract>
+        <KeywordList>
+          <Keyword>Roads</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="144.8607879004856" miny="-44.01262909951439" maxx="148.60973209951442" maxy="-40.26368490048561"/>
+        <BoundingBox SRS="EPSG:4326" minx="145.19754" miny="-43.423512" maxx="148.27298000000002" maxy="-40.852802"/>
+        <Style>
+          <Name>simple_roads</Name>
+          <Title>Default Styler for simple road segments</Title>
+          <Abstract>Light red line, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_state_boundaries</Name>
+        <Title>Tasmania state boundaries</Title>
+        <Abstract>Tasmania state boundaries</Abstract>
+        <KeywordList>
+          <Keyword>tasmania_state_boundaries</Keyword>
+          <Keyword>Tasmania</Keyword>
+          <Keyword>boundaries</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="142.70637712387594" miny="-45.06157887612408" maxx="149.60758787612411" maxy="-38.16036812387592"/>
+        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+        <Style>
+          <Name>green</Name>
+          <Title>Green polygon</Title>
+          <Abstract>Green fill with black outline</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_state_boundaries"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_water_bodies</Name>
+        <Title>Tasmania water bodies</Title>
+        <Abstract>Tasmania water bodies</Abstract>
+        <KeywordList>
+          <Keyword>Lakes</Keyword>
+          <Keyword>Bodies</Keyword>
+          <Keyword>Australia</Keyword>
+          <Keyword>Water</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="145.82989373832018" miny="-43.16951476167979" maxx="147.3614212616798" maxy="-41.63798723832021"/>
+        <BoundingBox SRS="EPSG:4326" minx="145.97161899999998" miny="-43.031944" maxx="147.219696" maxy="-41.775558"/>
+        <Style>
+          <Name>cite_lakes</Name>
+          <Title>Blue lake</Title>
+          <Abstract>A blue fill, solid black outline style</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_water_bodies"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:states</Name>
+        <Title>USA Population</Title>
+        <Abstract>This is some census data on the states.</Abstract>
+        <KeywordList>
+          <Keyword>census</Keyword>
+          <Keyword>united</Keyword>
+          <Keyword>boundaries</Keyword>
+          <Keyword>state</Keyword>
+          <Keyword>states</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-131.05615308855994" miny="1.958333411440066" maxx="-60.645117911440046" maxy="72.36936858855995"/>
+        <BoundingBox SRS="EPSG:4326" minx="-124.73142200000001" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
+        <Style>
+          <Name>population</Name>
+          <Title>Population in the United States</Title>
+          <Abstract>A sample filter that filters the United States into three
+        categories of population, drawn in different colors</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:states"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:giant_polygon</Name>
+        <Title>World rectangle</Title>
+        <Abstract>A simple rectangular polygon covering most of the world, it\'s only used for the purpose of providing a background (WMS bgcolor could be used instead)</Abstract>
+        <KeywordList>
+          <Keyword>DS_giant_polygon</Keyword>
+          <Keyword>giant_polygon</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-257.0843245637291" miny="-257.0843245637291" maxx="257.0843245637291" maxy="257.0843245637291"/>
+        <BoundingBox SRS="EPSG:4326" minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
+        <Style>
+          <Name>giant_polygon</Name>
+          <Title>Border-less gray fill</Title>
+          <Abstract>Light gray polygon fill without a border</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:giant_polygon"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:Arc_Sample</Name>
+        <Title>Global annual rainfall</Title>
+        <Abstract>Global annual rainfall in ArcGrid format</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>arcGridSample</Keyword>
+          <Keyword>arcGridSample_Coverage</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
+        <BoundingBox SRS="EPSG:4326" minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Arc_Sample"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:Img_Sample</Name>
+        <Title>North America sample imagery</Title>
+        <Abstract>A very rough imagery of North America</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>worldImageSample</Keyword>
+          <Keyword>worldImageSample_Coverage</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>
+        <BoundingBox SRS="EPSG:4326" minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Img_Sample"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:mosaic</Name>
+        <Title>Sample PNG mosaic</Title>
+        <Abstract>Subsampled satellite imagery loaded as a mosaic of PNG images</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>mosaic</Keyword>
+          <Keyword>mosaic</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="6.34617490847439" miny="36.4917718219401" maxx="20.8296831527815" maxy="46.5907669751351"/>
+        <BoundingBox SRS="EPSG:4326" minx="6.34617490847439" miny="36.4917718219401" maxx="20.8296831527815" maxy="46.5907669751351"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:mosaic"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:Pk50095</Name>
+        <Title>Sample scanned and georerenced map</Title>
+        <Abstract>This is a sample for the world image format (wld + prj + tiff)</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>img_sample2</Keyword>
+          <Keyword>Pk50095</Keyword>
+        </KeywordList>
+        <SRS>EPSG:32633</SRS>
+        <LatLonBoundingBox minx="12.999446822650462" miny="46.722110379286" maxx="13.308182612644663" maxy="46.91359611878293"/>
+        <BoundingBox SRS="EPSG:32633" minx="347649.93086859107" miny="5176214.082539256" maxx="370725.976428591" maxy="5196961.352859256"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Pk50095"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:sfdem</Name>
+        <Title>sfdem is a Tagged Image File Format with Geographic information</Title>
+        <Abstract>Generated from sfdem</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>sfdem</Keyword>
+          <Keyword>sfdem</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.87108701853181" miny="44.370187074132616" maxx="-103.62940739432703" maxy="44.5016011535299"/>
+        <BoundingBox SRS="EPSG:26713" minx="589980.0" miny="4913700.0" maxx="609000.0" maxy="4928010.0"/>
+        <Style>
+          <Name>dem</Name>
+          <Title>Simple DEM style</Title>
+          <Abstract>Classic elevation color progression</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://publicus.opengeo.org:80/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:sfdem"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="0">
+        <Name>spearfish</Name>
+        <Title>spearfish</Title>
+        <Abstract>Layer-Group type layer: spearfish</Abstract>
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.87799562257162" miny="44.37244213023845" maxx="-103.62286957414864" maxy="44.5023266635277"/>
+        <BoundingBox SRS="EPSG:26713" minx="589425.9342365642" miny="4913959.224611808" maxx="609518.6719560538" maxy="4928082.949945881"/>
+      </Layer>
+      <Layer queryable="0">
+        <Name>tasmania</Name>
+        <Title>tasmania</Title>
+        <Abstract>Layer-Group type layer: tasmania</Abstract>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+      </Layer>
+      <Layer queryable="0">
+        <Name>tiger-ny</Name>
+        <Title>tiger-ny</Title>
+        <Abstract>Layer-Group type layer: tiger-ny</Abstract>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>
+      </Layer>
+    </Layer>
+  </Capability>
+</WMT_MS_Capabilities>--></div>
+
 </body> 
 </html> 

Copied: sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_3_0.html (from rev 10919, trunk/openlayers/tests/Format/WMSCapabilities/v1_3_0.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_3_0.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/WMSCapabilities/v1_3_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,578 @@
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+    function test_layers(t) {
+
+        t.plan(22);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        var layers = {};
+        for (var i=0, len=capability.layers.length; i<len; i++) {
+            if ("name" in capability.layers[i]) {
+                layers[ capability.layers[i].name ] = capability.layers[i];
+            }
+        }
+
+        var rootlayer = capability.layers[ capability.layers.length - 1];
+
+        t.eq(rootlayer.srs,
+             {"CRS:84": true},
+             "SRS parsed correctly for root layer");
+        t.eq(layers["ROADS_RIVERS"].srs,
+             {"CRS:84": true, "EPSG:26986": true},
+             "Inheritance of SRS handled correctly when adding SRSes");
+        t.eq(layers["Temperature"].srs,
+             {"CRS:84": true},
+             "Inheritance of SRS handled correctly when redeclaring an inherited SRS");
+
+        var bbox = layers["ROADS_RIVERS"].bbox["EPSG:26986"];
+        t.eq(bbox.bbox,
+             [189000, 834000, 285000, 962000],
+             "Correct bbox from BoundingBox");
+        t.eq(bbox.res, {x: 1, y: 1}, "Correct resolution");
+
+        bbox = layers["ROADS_1M"].bbox["EPSG:26986"];
+        t.eq(bbox.bbox,
+             [189000, 834000, 285000, 962000],
+             "Correctly inherited bbox");
+        t.eq(bbox.res, {x: 1, y: 1}, "Correctly inherited resolution");
+
+
+        var identifiers = layers["ROADS_RIVERS"].identifiers;
+        var authorities = layers["ROADS_RIVERS"].authorityURLs;
+
+        t.ok(identifiers, "got identifiers from layer ROADS_RIVERS");
+        t.ok("DIF_ID" in identifiers,
+             "authority attribute from Identifiers parsed correctly");
+        t.eq(identifiers["DIF_ID"],
+             "123456",
+             "Identifier value parsed correctly");
+        t.ok("DIF_ID" in authorities,
+             "AuthorityURLs parsed and inherited correctly");
+        t.eq(authorities["DIF_ID"],
+             "http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html",
+             "OnlineResource in AuthorityURLs parsed correctly");
+
+        var featurelist = layers["ROADS_RIVERS"].featureListURL;
+        t.ok(featurelist, "layer has FeatureListURL");
+        t.eq(featurelist.format,
+             "XML",
+             "FeatureListURL format parsed correctly");
+        t.eq(featurelist.href,
+             "http://www.university.edu/data/roads_rivers.gml",
+             "FeatureListURL OnlineResource parsed correctly");
+
+        t.eq(layers["Pressure"].queryable,
+             true,
+             "queryable property inherited correctly");
+        t.eq(layers["ozone_image"].queryable,
+             false,
+             "queryable property has correct default value");
+        t.eq(layers["population"].cascaded,
+             1,
+             "cascaded property parsed correctly");
+        t.eq(layers["ozone_image"].fixedWidth,
+             512,
+             "fixedWidth property correctly parsed");
+        t.eq(layers["ozone_image"].fixedHeight,
+             256,
+             "fixedHeight property correctly parsed");
+        t.eq(layers["ozone_image"].opaque,
+             true,
+             "opaque property parsed correctly");
+        t.eq(layers["ozone_image"].noSubsets,
+             true,
+             "noSubsets property parsed correctly");
+
+
+    }
+
+    function test_dimensions(t) {
+
+        t.plan(8);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        var layers = {};
+        for (var i=0, len=capability.layers.length; i<len; i++) {
+            if ("name" in capability.layers[i]) {
+                layers[ capability.layers[i].name ] = capability.layers[i];
+            }
+        }
+
+        var time = layers["Clouds"].dimensions.time;
+        t.eq(time["default"], "2000-08-22", "Default time value parsed correctly");
+        t.eq(time.values.length, 1, "Currect number of time extent values/periods");
+        t.eq(time.values[0], "1999-01-01/2000-08-22/P1D", "Time extent values parsed correctly");
+
+        var elevation = layers["Pressure"].dimensions.elevation;
+        t.eq(elevation.units, "CRS:88", "Dimension units parsed correctly");
+        t.eq(elevation["default"], "0", "Default elevation value parsed correctly");
+        t.eq(elevation.nearestVal, true, "NearestValue parsed correctly");
+        t.eq(elevation.multipleVal, false, "Absense of MultipleValues handled correctly");
+        t.eq(elevation.values,
+             ["0","1000","3000","5000","10000"],
+             "Parsing of comma-separated values done correctly");
+
+
+    }
+
+    function test_contactinfo(t) {
+        t.plan(14);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var service = obj.service;
+
+        var contactinfo = service.contactInformation;
+        t.ok(contactinfo, "object contains contactInformation property");
+
+        var personPrimary = contactinfo.personPrimary;
+        t.ok(personPrimary, "object contains personPrimary property");
+
+        t.eq(personPrimary.person, "Jeff Smith", "ContactPerson parsed correctly");
+        t.eq(personPrimary.organization, "NASA", "ContactOrganization parsed correctly");
+
+        t.eq(contactinfo.position,
+             "Computer Scientist",
+             "ContactPosition parsed correctly");
+
+
+        var addr = contactinfo.contactAddress;
+        t.ok(addr, "object contains contactAddress property");
+
+        t.eq(addr.type, "postal", "AddressType parsed correctly");
+        t.eq(addr.address,
+             "NASA Goddard Space Flight Center",
+             "Address parsed correctly");
+        t.eq(addr.city, "Greenbelt", "City parsed correctly");
+        t.eq(addr.stateOrProvince, "MD", "StateOrProvince parsed correctly");
+        t.eq(addr.postcode, "20771", "PostCode parsed correctly");
+        t.eq(addr.country, "USA", "Country parsed correctly");
+
+        t.eq(contactinfo.phone,
+             "+1 301 555-1212",
+             "ContactVoiceTelephone parsed correctly");
+        t.eq(contactinfo.email,
+             "user at host.com",
+             "ContactElectronicMailAddress parsed correctly");
+    }
+
+    function test_feesAndConstraints(t) {
+        t.plan(2);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var service = obj.service;
+
+        t.ok(! ("fees" in service), "Fees=none handled correctly");
+        t.ok(! ("accessConstraints" in service), "AccessConstraints=none handled correctly");
+    }
+
+    function test_requests(t) {
+        t.plan(6);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var request = obj.capability.request;
+
+        t.ok(request, "request property exists");
+        t.ok("getmap" in request, "got GetMap request");
+
+        t.ok("getfeatureinfo" in request, "got GetFeatureInfo request");
+        t.eq(request.getfeatureinfo.formats,
+             ["text/xml", "text/plain", "text/html"],
+             "GetFeatureInfo formats correctly parsed");
+
+        var exception = obj.capability.exception;
+        t.ok(exception, "exception property exists");
+        t.eq(exception.formats,
+             ["XML", "INIMAGE", "BLANK"],
+             "Exception Format parsed");
+    }
+
+    function test_ogc(t) {
+        t.plan(14);
+
+        /*
+         * Set up
+         */
+
+        // needed for the minScale/maxScale test, see below
+        var dpi = OpenLayers.DOTS_PER_INCH;
+        OpenLayers.DOTS_PER_INCH = 90.71;
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+        var capability = obj.capability;
+
+        /*
+         * Test
+         */
+
+        var attribution = capability.layers[2].attribution;
+        t.eq(attribution.title, "State College University", "attribution title parsed correctly.");
+        t.eq(attribution.href, "http://www.university.edu/", "attribution href parsed correctly.")
+        t.eq(attribution.logo.href, "http://www.university.edu/icons/logo.gif", "attribution logo url parsed correctly.");
+        t.eq(attribution.logo.format, "image/gif", "attribution logo format parsed correctly.");
+        t.eq(attribution.logo.width, "100", "attribution logo width parsed correctly.");
+        t.eq(attribution.logo.height, "100", "attribution logo height parsed correctly.");
+
+        var keywords = capability.layers[0].keywords;
+        t.eq(keywords.length, 3, "layer has 3 keywords.");
+        t.eq(keywords[0].value, "road", "1st keyword parsed correctly.");
+
+        var metadataURLs = capability.layers[0].metadataURLs;
+        t.eq(metadataURLs.length, 2, "layer has 2 metadata urls.");
+        t.eq(metadataURLs[0].type, "FGDC:1998", "type parsed correctly.");
+        t.eq(metadataURLs[0].format, "text/plain", "format parsed correctly.");
+        t.eq(metadataURLs[0].href, "http://www.university.edu/metadata/roads.txt", "href parsed correctly.");
+
+        /*
+        Test minScale and maxScale
+        */
+        var minScale = 250000;
+        var maxScale = 1000;
+        t.eq(capability.layers[0].minScale, minScale.toPrecision(16), "layer.minScale is correct");
+        t.eq(capability.layers[0].maxScale, maxScale.toPrecision(16), "layer.maxScale is correct");
+
+        /*
+         * Tear down
+         */
+
+        OpenLayers.DOTS_PER_INCH = dpi;
+    }
+
+    function test_WMS13specials(t) {
+        t.plan(3);
+
+        var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+        var doc = new OpenLayers.Format.XML().read(xml);
+
+        var obj = new OpenLayers.Format.WMSCapabilities().read(doc);
+
+        t.eq(obj.service.layerLimit, 16, "LayerLimit parsed correctly");
+        t.eq(obj.service.maxHeight, 2048, "MaxHeight parsed correctly");
+        t.eq(obj.service.maxWidth, 2048, "MaxWidth parsed correctly");
+
+    }
+
+    </script>
+</head>
+<body>
+
+<!--
+OGC example below taken from
+http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xml
+Changes:
+-removed comments
+-corrected typo in FeatureListURL Format XML with double quote
+-added MinScaleDenominator and MaxScaleDenominator
+-remove whitespace in Dimension tags
+-->
+<div id="ogcsample"><!--
+<?xml version='1.0' encoding="UTF-8"?>
+<WMS_Capabilities version="1.3.0" xmlns="http://www.opengis.net/wms"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd">
+<Service>
+  <Name>WMS</Name>
+  <Title>Acme Corp. Map Server</Title>
+  <Abstract>Map Server maintained by Acme Corporation.  Contact: webmaster at wmt.acme.com.  High-quality maps showing roadrunner nests and possible ambush locations.</Abstract>
+
+  <KeywordList>
+    <Keyword>bird</Keyword>
+    <Keyword>roadrunner</Keyword>
+    <Keyword>ambush</Keyword>
+  </KeywordList>
+  <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+   xlink:href="http://hostname/" />
+
+
+  <ContactInformation>
+    <ContactPersonPrimary>
+      <ContactPerson>Jeff Smith</ContactPerson>
+      <ContactOrganization>NASA</ContactOrganization>
+    </ContactPersonPrimary>
+    <ContactPosition>Computer Scientist</ContactPosition>
+
+    <ContactAddress>
+      <AddressType>postal</AddressType>
+      <Address>NASA Goddard Space Flight Center</Address>
+      <City>Greenbelt</City>
+      <StateOrProvince>MD</StateOrProvince>
+      <PostCode>20771</PostCode>
+
+      <Country>USA</Country>
+    </ContactAddress>
+    <ContactVoiceTelephone>+1 301 555-1212</ContactVoiceTelephone>
+    <ContactElectronicMailAddress>user at host.com</ContactElectronicMailAddress>
+  </ContactInformation>
+
+  <Fees>none</Fees>
+
+  <AccessConstraints>none</AccessConstraints>
+  <LayerLimit>16</LayerLimit>
+  <MaxWidth>2048</MaxWidth>
+  <MaxHeight>2048</MaxHeight>
+</Service>
+<Capability>
+  <Request>
+    <GetCapabilities>
+
+      <Format>text/xml</Format>
+      <DCPType>
+        <HTTP>
+          <Get>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname/path?" />
+          </Get>
+          <Post>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname/path?" />
+
+          </Post>
+        </HTTP>
+      </DCPType>
+    </GetCapabilities>
+    <GetMap>
+      <Format>image/gif</Format>
+      <Format>image/png</Format>
+      <Format>image/jpeg</Format>
+
+      <DCPType>
+        <HTTP>
+          <Get>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname/path?" />
+          </Get>
+        </HTTP>
+      </DCPType>
+    </GetMap>
+
+    <GetFeatureInfo>
+      <Format>text/xml</Format>
+      <Format>text/plain</Format>
+      <Format>text/html</Format>
+      <DCPType>
+        <HTTP>
+          <Get>
+
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+             xlink:type="simple"
+             xlink:href="http://hostname/path?" />
+          </Get>
+        </HTTP>
+      </DCPType>
+    </GetFeatureInfo>
+  </Request>
+  <Exception>
+    <Format>XML</Format>
+
+    <Format>INIMAGE</Format>
+    <Format>BLANK</Format>
+  </Exception>
+  <Layer>
+    <Title>Acme Corp. Map Server</Title>
+    <CRS>CRS:84</CRS>
+
+    <AuthorityURL name="DIF_ID">
+      <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+       xlink:href="http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html" />
+    </AuthorityURL>
+    <Layer>
+
+      <Name>ROADS_RIVERS</Name>
+      <Title>Roads and Rivers</Title>
+
+      <CRS>EPSG:26986</CRS>
+      <EX_GeographicBoundingBox>
+        <westBoundLongitude>-71.63</westBoundLongitude>
+        <eastBoundLongitude>-70.78</eastBoundLongitude>
+        <southBoundLatitude>41.75</southBoundLatitude>
+        <northBoundLatitude>42.90</northBoundLatitude>
+
+      </EX_GeographicBoundingBox>
+      <BoundingBox CRS="CRS:84"
+       minx="-71.63" miny="41.75" maxx="-70.78" maxy="42.90" resx="0.01" resy="0.01"/>
+      <BoundingBox CRS="EPSG:26986"
+       minx="189000" miny="834000" maxx="285000" maxy="962000" resx="1" resy="1" />
+      <Attribution>
+        <Title>State College University</Title>
+        <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+         xlink:href="http://www.university.edu/" />
+
+        <LogoURL width="100" height="100">
+          <Format>image/gif</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/icons/logo.gif" />
+        </LogoURL>
+      </Attribution>
+      <Identifier authority="DIF_ID">123456</Identifier>
+      <FeatureListURL>
+
+        <Format>XML</Format>
+        <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
+         xlink:href="http://www.university.edu/data/roads_rivers.gml" />
+      </FeatureListURL>
+      <Style>
+        <Name>USGS</Name>
+        <Title>USGS Topo Map Style</Title>
+        <Abstract>Features are shown in a style like that used in USGS topographic maps.</Abstract>
+
+        <LegendURL width="72" height="72">
+          <Format>image/gif</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/legends/usgs.gif" />
+        </LegendURL>
+        <StyleSheetURL>
+          <Format>text/xsl</Format>
+
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/stylesheets/usgs.xsl" />
+        </StyleSheetURL>
+      </Style>
+      <MinScaleDenominator>1000</MinScaleDenominator>
+      <MaxScaleDenominator>250000</MaxScaleDenominator>
+      <Layer queryable="1">
+        <Name>ROADS_1M</Name>
+        <Title>Roads at 1:1M scale</Title>
+        <Abstract>Roads at a scale of 1 to 1 million.</Abstract>
+
+        <KeywordList>
+          <Keyword>road</Keyword>
+          <Keyword>transportation</Keyword>
+          <Keyword>atlas</Keyword>
+        </KeywordList>
+        <Identifier authority="DIF_ID">123456</Identifier>
+        <MetadataURL type="FGDC:1998">
+
+                <Format>text/plain</Format>
+                <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+                 xlink:type="simple"
+                 xlink:href="http://www.university.edu/metadata/roads.txt" />
+             </MetadataURL>
+        <MetadataURL type="ISO19115:2003">
+               <Format>text/xml</Format>
+               <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+                xlink:type="simple"
+                xlink:href="http://www.university.edu/metadata/roads.xml" />
+             </MetadataURL>
+
+        <Style>
+          <Name>ATLAS</Name>
+          <Title>Road atlas style</Title>
+          <Abstract>Roads are shown in a style like that used in a commercial road atlas.</Abstract>
+        <LegendURL width="72" height="72">
+          <Format>image/gif</Format>
+          <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
+           xlink:type="simple"
+           xlink:href="http://www.university.edu/legends/atlas.gif" />
+
+        </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>RIVERS_1M</Name>
+        <Title>Rivers at 1:1M scale</Title>
+        <Abstract>Rivers at a scale of 1 to 1 million.</Abstract>
+
+        <KeywordList>
+          <Keyword>river</Keyword>
+          <Keyword>canal</Keyword>
+          <Keyword>waterway</Keyword>
+        </KeywordList>
+      </Layer>
+    </Layer>
+
+    <Layer queryable="1">
+      <Title>Weather Forecast Data</Title>
+      <CRS>CRS:84</CRS>
+
+      <EX_GeographicBoundingBox>
+        <westBoundLongitude>-180</westBoundLongitude>
+        <eastBoundLongitude>180</eastBoundLongitude>
+
+        <southBoundLatitude>-90</southBoundLatitude>
+        <northBoundLatitude>90</northBoundLatitude>
+      </EX_GeographicBoundingBox>
+      <Dimension name="time" units="ISO8601" default="2000-08-22">1999-01-01/2000-08-22/P1D</Dimension>
+      <Layer>
+
+        <Name>Clouds</Name>
+        <Title>Forecast cloud cover</Title>
+      </Layer>
+      <Layer>
+        <Name>Temperature</Name>
+        <Title>Forecast temperature</Title>
+      </Layer>
+
+      <Layer>
+        <Name>Pressure</Name>
+        <Title>Forecast barometric pressure</Title>
+         <Dimension name="elevation" units="EPSG:5030" />
+         <Dimension name="time" units="ISO8601" default="2000-08-22">
+           1999-01-01/2000-08-22/P1D</Dimension>
+
+         <Dimension name="elevation" units="CRS:88" default="0" nearestValue="1">0,1000,3000,5000,10000</Dimension>
+      </Layer>
+    </Layer>
+    <Layer opaque="1" noSubsets="1" fixedWidth="512" fixedHeight="256">
+      <Name>ozone_image</Name>
+      <Title>Global ozone distribution (1992)</Title>
+
+      <EX_GeographicBoundingBox>
+        <westBoundLongitude>-180</westBoundLongitude>
+        <eastBoundLongitude>180</eastBoundLongitude>
+        <southBoundLatitude>-90</southBoundLatitude>
+        <northBoundLatitude>90</northBoundLatitude>
+      </EX_GeographicBoundingBox>
+      <Dimension name="time" units="ISO8601" default="1992">1992</Dimension>
+
+    </Layer>
+    <Layer cascaded="1">
+      <Name>population</Name>
+      <Title>World population, annual</Title>
+      <EX_GeographicBoundingBox>
+        <westBoundLongitude>-180</westBoundLongitude>
+
+        <eastBoundLongitude>180</eastBoundLongitude>
+        <southBoundLatitude>-90</southBoundLatitude>
+        <northBoundLatitude>90</northBoundLatitude>
+      </EX_GeographicBoundingBox>
+      <Dimension name="time" units="ISO8601" default="2000">1990/2000/P1Y</Dimension>
+    </Layer>
+  </Layer>
+
+</Capability>
+</WMS_Capabilities>
+--></div>
+
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Format/WMSDescribeLayer.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMSDescribeLayer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMSDescribeLayer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,7 +4,7 @@
     <script type="text/javascript">
     
     function test_read_WMSDescribeLayer(t) {
-        t.plan(4);
+        t.plan(5);
        
         var parser = new OpenLayers.Format.WMSDescribeLayer();
 
@@ -29,6 +29,9 @@
         t.eq(res[0].typeName, "topp:states",
             "Properly parses typeName");
 
+        t.eq(res[0].layerName, "topp:states",
+            "Properly parses name");
+
     }
 
     </script> 

Modified: sandbox/ahocevar/playground/tests/Format/WMSGetFeatureInfo.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMSGetFeatureInfo.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMSGetFeatureInfo.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -52,7 +52,7 @@
     }
 
     function test_read_msGMLOutput(t) {
-        t.plan(7);
+        t.plan(12);
         
         var parser = new OpenLayers.Format.WMSGetFeatureInfo();
 
@@ -96,6 +96,7 @@
             '</msGMLOutput>';
 
         features = parser.read(text);
+
         t.eq(features.length, 1,
              "Parsed 1 feature in total");
 
@@ -105,6 +106,13 @@
         t.eq(features[0].type, 'AAA64',
              "Parsed the layer name correctly");
 
+        var bounds = features[0].bounds;
+        t.ok(bounds instanceof OpenLayers.Bounds, "feature given a bounds");
+        t.eq(bounds.left.toFixed(3), "107397.266", "Bounds left parsed correctly");
+        t.eq(bounds.right.toFixed(3), "116568.188", "Bounds right parsed correctly");
+        t.eq(bounds.bottom.toFixed(3), "460681.063", "Bounds bottom parsed correctly");
+        t.eq(bounds.top.toFixed(3), "480609.250", "Bounds top parsed correctly");
+
         // read 2 features from 2 layers
         text = 
             '<?xml version="1.0" encoding="ISO-8859-1"?>' +
@@ -263,7 +271,6 @@
 
     }
     
-
     </script> 
 </head> 
 <body>

Deleted: sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html
===================================================================
--- trunk/openlayers/tests/Format/WMTSCapabilities/v1_0_0.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,323 +0,0 @@
-<html>
-<head>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-
-        function test_ows(t) {
-            t.plan(17);
-            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
-            var doc = new OpenLayers.Format.XML().read(xml);
-            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
-            // ows:ServiceIdentification
-            var serviceIdentification = obj.serviceIdentification;
-            t.eq(serviceIdentification.title, "Web Map Tile Service", "ows:ServiceIdentification title is correct");
-            t.eq(serviceIdentification.serviceTypeVersion, "1.0.0", "ows:ServiceIdentification serviceTypeVersion is correct");
-            t.eq(serviceIdentification.serviceType.value, "OGC WMTS", "ows:ServiceIdentification serviceType is correct");
-
-            // ows:ServiceProvider
-            var serviceProvider = obj.serviceProvider;
-            t.eq(serviceProvider.providerName, "MiraMon", "ows:ServiceProvider providerName is correct");
-            t.eq(serviceProvider.providerSite, "http://www.creaf.uab.es/miramon", "ows:ServiceProvider providerSite is correct");
-            t.eq(serviceProvider.serviceContact.individualName, "Joan Maso Pau", "ows:ServiceProvider individualName is correct");
-            t.eq(serviceProvider.serviceContact.positionName, "Senior Software Engineer", "ows:ServiceProvider positionName is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.administrativeArea, "Barcelona", "ows:ServiceProvider address administrativeArea is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.city, "Bellaterra", "ows:ServiceProvider address city is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.country, "Spain", "ows:ServiceProvider address country is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.deliveryPoint, "Fac Ciencies UAB", "ows:ServiceProvider address deliveryPoint is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.electronicMailAddress, "joan.maso at uab.es", "ows:ServiceProvider address electronicMailAddress is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.address.postalCode, "08193", "ows:ServiceProvider address postalCode is correct");
-            t.eq(serviceProvider.serviceContact.contactInfo.phone.voice, "+34 93 581 1312", "ows:ServiceProvider phone voice is correct");
-
-            // ows:OperationsMetadata
-            var operationsMetadata = obj.operationsMetadata;
-            t.eq(operationsMetadata.GetCapabilities.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetCapabilities url is correct");
-            t.eq(operationsMetadata.GetFeatureInfo.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetFeatureInfo url is correct");
-            t.eq(operationsMetadata.GetTile.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetTile url is correct");
-        }
-    
-        function test_layers(t) {
-            t.plan(21);
-            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
-            var doc = new OpenLayers.Format.XML().read(xml);
-    
-            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
-            var contents = obj.contents;
-    
-            var numOfLayers = contents.layers.length;
-            t.eq(numOfLayers, 1, "correct count of layers");
-
-            var layer = contents.layers[0];
-            t.eq(layer.abstract, "Coastline/shorelines (BA010)", "layer abstract is correct");
-            t.eq(layer.identifier, "coastlines", "layer identifier is correct");
-            t.eq(layer.title, "Coastlines", "layer title is correct");
-
-            var numOfFormats = layer.formats.length;
-            t.eq(numOfFormats, 2, "correct count of formats");
-            t.eq(layer.formats[0], "image/png", "format image/png is correct");
-            t.eq(layer.formats[1], "image/gif", "format image/gif is correct");
-
-            var numOfStyles = layer.styles.length;
-            t.eq(numOfStyles, 2, "correct count of styles");
-            t.eq(layer.styles[0].identifier, "DarkBlue", "style 0 identifier is correct");
-            t.eq(layer.styles[0].isDefault, true, "style 0 isDefault is correct");
-            t.eq(layer.styles[0].title, "Dark Blue", "style 0 title is correct");
-            t.eq(layer.styles[1].identifier, "thickAndRed", "style 1 identifier is correct");
-            t.ok(!layer.styles[1].isDefault, "style 1 isDefault is correct");
-            t.eq(layer.styles[1].title, "Thick And Red", "style 1 title is correct");
-            //t.eq(layer.styles[1].abstract, "Specify this style if you want your maps to have thick red coastlines. ", "style 1 abstract is correct");
-
-            t.eq(layer.tileMatrixSetLinks.length, 1, "correct count of tileMatrixSetLinks");
-            t.eq(layer.tileMatrixSetLinks[0].tileMatrixSet, "BigWorld", "tileMatrixSet is correct");
-
-            var wgs84Bbox = layer.bounds;
-            t.ok(wgs84Bbox instanceof OpenLayers.Bounds, "wgs84BoudingBox instance of OpenLayers.Bounds");
-            t.eq(wgs84Bbox.left, -180.0, "wgs84BoudingBox left is correct");
-            t.eq(wgs84Bbox.right, 180.0, "wgs84BoudingBox right is correct");
-            t.eq(wgs84Bbox.bottom, -90.0, "wgs84BoudingBox bottom is correct");
-            t.eq(wgs84Bbox.top, 90.0, "wgs84BoudingBox top is correct");
-            
-        }
-
-        function test_tileMatrixSets(t) {
-            t.plan(19);
-            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
-            var doc = new OpenLayers.Format.XML().read(xml);
-    
-            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
-
-            var tileMatrixSets = obj.contents.tileMatrixSets;
-            t.ok(tileMatrixSets['BigWorld'], "tileMatrixSets 'BigWorld' found");
-            var bigWorld = tileMatrixSets['BigWorld'];
-            t.eq(bigWorld.identifier, "BigWorld", "tileMatrixSets identifier is correct");
-            t.eq(bigWorld.matrixIds.length, 2, "tileMatrix count is correct");
-            t.eq(bigWorld.matrixIds[0].identifier, "1e6", "tileMatrix 0 identifier is correct");
-            t.eq(bigWorld.matrixIds[0].matrixHeight, 50000, "tileMatrix 0 matrixHeight is correct");
-            t.eq(bigWorld.matrixIds[0].matrixWidth, 60000, "tileMatrix 0 matrixWidth is correct");
-            t.eq(bigWorld.matrixIds[0].scaleDenominator, 1000000, "tileMatrix 0 scaleDenominator is correct");
-            t.eq(bigWorld.matrixIds[0].tileWidth, 256, "tileMatrix 0 tileWidth is correct");
-            t.eq(bigWorld.matrixIds[0].tileHeight, 256, "tileMatrix 0 tileHeight is correct");
-            t.eq(bigWorld.matrixIds[0].topLeftCorner.lon, -180, "tileMatrix 0 topLeftCorner.lon is correct");
-            t.eq(bigWorld.matrixIds[0].topLeftCorner.lat, 84, "tileMatrix 0 topLeftCorner.lat is correct");
-
-            t.eq(bigWorld.matrixIds[1].identifier, "2.5e6", "tileMatrix 1 identifier is correct");
-            t.eq(bigWorld.matrixIds[1].matrixHeight, 7000, "tileMatrix 1 matrixHeight is correct");
-            t.eq(bigWorld.matrixIds[1].matrixWidth, 9000, "tileMatrix 1 matrixWidth is correct");
-            t.eq(bigWorld.matrixIds[1].scaleDenominator, 2500000, "tileMatrix 1 scaleDenominator is correct");
-            t.eq(bigWorld.matrixIds[1].tileWidth, 256, "tileMatrix 1 tileWidth is correct");
-            t.eq(bigWorld.matrixIds[1].tileHeight, 256, "tileMatrix 1 tileHeight is correct");
-            t.eq(bigWorld.matrixIds[1].topLeftCorner.lon, -180, "tileMatrix 1 topLeftCorner.lon is correct");
-            t.eq(bigWorld.matrixIds[1].topLeftCorner.lat, 84, "tileMatrix 1 topLeftCorner.lat is correct");
-        }
-        
-        function test_createLayer(t) {
-            t.plan(6);
-            
-            var format = new OpenLayers.Format.WMTSCapabilities();
-
-            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
-            var doc = new OpenLayers.Format.XML().read(xml);
-    
-            var caps = format.read(doc);
-            var layer;
-            
-            var success = true;
-            try {
-                // incomplete config (missing matrixSet)
-                layer = format.createLayer(caps, {
-                    layer: "coastlines"
-                });
-            } catch (err) {
-                success = false;
-            }
-            t.ok(!success, "createLayer throws error if provided incomplete layer config");
-            
-            // bogus layer identifier
-            layer = format.createLayer(caps, {
-                layer: "foo",
-                matrixSet: "BigWorld"
-            });
-            t.eq(layer, undefined, "createLayer returns undefined given bad layer identifier");
-            
-            // bogus matrixSet identifier
-            layer = format.createLayer(caps, {
-                layer: "coastlines",
-                matrixSet: "TheWorld"
-            });
-            t.eq(layer, undefined, "createLayer returns undefined given bad matrixSet identifier");
-            
-            layer = format.createLayer(caps, {
-                layer: "coastlines",
-                matrixSet: "BigWorld"
-            });
-            t.ok(layer instanceof OpenLayers.Layer.WMTS, "correct instance");
-            
-            t.eq(layer.matrixIds.length, 2, "correct matrixIds length");
-            t.eq(layer.name, "Coastlines", "correct layer title");
-            
-        }
-        
-    </script>
-</head>
-<body>
-
-<!--
-OGC example below taken from
-http://schemas.opengis.net/wmts/1.0/examples/wmtsGetCapabilities_response.xml
--->
-<div id="ogcsample"><!--
-<?xml version="1.0" encoding="UTF-8"?>
-<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
-    <ows:ServiceIdentification>
-        <ows:Title>Web Map Tile Service</ows:Title>
-        <ows:Abstract>Service that contrains the map access interface to some TileMatrixSets</ows:Abstract>
-        <ows:Keywords>
-            <ows:Keyword>tile</ows:Keyword>
-            <ows:Keyword>tile matrix set</ows:Keyword>
-            <ows:Keyword>map</ows:Keyword>
-        </ows:Keywords>
-        <ows:ServiceType>OGC WMTS</ows:ServiceType>
-        <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
-        <ows:Fees>none</ows:Fees>
-        <ows:AccessConstraints>none</ows:AccessConstraints>
-    </ows:ServiceIdentification>
-    <ows:ServiceProvider>
-        <ows:ProviderName>MiraMon</ows:ProviderName>
-        <ows:ProviderSite xlink:href="http://www.creaf.uab.es/miramon"/>
-        <ows:ServiceContact>
-            <ows:IndividualName>Joan Maso Pau</ows:IndividualName>
-            <ows:PositionName>Senior Software Engineer</ows:PositionName>
-            <ows:ContactInfo>
-                <ows:Phone>
-                    <ows:Voice>+34 93 581 1312</ows:Voice>
-                    <ows:Facsimile>+34 93 581 4151</ows:Facsimile>
-                </ows:Phone>
-                <ows:Address>
-                    <ows:DeliveryPoint>Fac Ciencies UAB</ows:DeliveryPoint>
-                    <ows:City>Bellaterra</ows:City>
-                    <ows:AdministrativeArea>Barcelona</ows:AdministrativeArea>
-                    <ows:PostalCode>08193</ows:PostalCode>
-                    <ows:Country>Spain</ows:Country>
-                    <ows:ElectronicMailAddress>joan.maso at uab.es</ows:ElectronicMailAddress>
-                </ows:Address>
-            </ows:ContactInfo>
-        </ows:ServiceContact>
-    </ows:ServiceProvider>
-    <ows:OperationsMetadata>
-        <ows:Operation name="GetCapabilities">
-            <ows:DCP>
-                <ows:HTTP>
-                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?">
-                        <ows:Constraint name="GetEncoding">
-                            <ows:AllowedValues>
-                                <ows:Value>KVP</ows:Value>
-                            </ows:AllowedValues>
-                        </ows:Constraint>
-                    </ows:Get>
-                </ows:HTTP>
-            </ows:DCP>
-        </ows:Operation>
-        <ows:Operation name="GetTile">
-            <ows:DCP>
-                <ows:HTTP>
-                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?"/>
-                </ows:HTTP>
-            </ows:DCP>
-        </ows:Operation>
-        <ows:Operation name="GetFeatureInfo">
-            <ows:DCP>
-                <ows:HTTP>
-                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?"/>
-                </ows:HTTP>
-            </ows:DCP>
-        </ows:Operation>
-    </ows:OperationsMetadata>
-    <Contents>
-        <Layer>
-            <ows:Title>Coastlines</ows:Title>
-            <ows:Abstract>Coastline/shorelines (BA010)</ows:Abstract>
-            <ows:WGS84BoundingBox>
-                <ows:LowerCorner>-180 -90</ows:LowerCorner>
-                <ows:UpperCorner>180 90</ows:UpperCorner>
-            </ows:WGS84BoundingBox>
-            <ows:Identifier>coastlines</ows:Identifier>
-            <Style isDefault="true">
-                <ows:Title>Dark Blue</ows:Title>
-                <ows:Identifier>DarkBlue</ows:Identifier>
-                <LegendURL format="image/png" xlink:href="http://www.miramon.uab.es/wmts/Coastlines/coastlines_darkBlue.png"/>
-            </Style>
-            <Style>
-                <ows:Title>Thick And Red</ows:Title>
-                <ows:Abstract>Specify this style if you want your maps to have thick red coastlines.
-                </ows:Abstract>
-                <ows:Identifier>thickAndRed</ows:Identifier>
-            </Style>
-            <Format>image/png</Format>
-            <Format>image/gif</Format>
-            <Dimension>
-                <ows:Title>Time</ows:Title>
-                <ows:Abstract>Monthly datasets</ows:Abstract>
-                <ows:Identifier>TIME</ows:Identifier>
-                <Value>2007-05</Value>
-                <Value>2007-06</Value>
-                <Value>2007-07</Value>
-            </Dimension>
-            <TileMatrixSetLink>
-                <TileMatrixSet>BigWorld</TileMatrixSet>
-            </TileMatrixSetLink>
-        </Layer>
-        <TileMatrixSet>        
-            <ows:Identifier>BigWorld</ows:Identifier>
-            <ows:SupportedCRS>urn:ogc:def:crs:OGC:1.3:CRS84</ows:SupportedCRS>
-            <TileMatrix>
-                <ows:Identifier>1e6</ows:Identifier>
-                <ScaleDenominator>1e6</ScaleDenominator>        
-                <TopLeftCorner>-180 84</TopLeftCorner>        
-                <TileWidth>256</TileWidth>
-                <TileHeight>256</TileHeight>        
-                <MatrixWidth>60000</MatrixWidth>
-                <MatrixHeight>50000</MatrixHeight>
-            </TileMatrix>
-            <TileMatrix>
-                <ows:Identifier>2.5e6</ows:Identifier>
-                <ScaleDenominator>2.5e6</ScaleDenominator>
-                <TopLeftCorner>-180 84</TopLeftCorner>
-                <TileWidth>256</TileWidth>
-                <TileHeight>256</TileHeight>
-                <MatrixWidth>9000</MatrixWidth>
-                <MatrixHeight>7000</MatrixHeight>
-            </TileMatrix>
-        </TileMatrixSet>
-    </Contents>
-    <Themes>
-        <Theme>
-            <ows:Title>Foundation</ows:Title>
-            <ows:Abstract>"Digital Chart Of The World" data</ows:Abstract>
-            <ows:Identifier>Foundation</ows:Identifier>
-            <Theme>
-                <ows:Title>Boundaries</ows:Title>
-                <ows:Identifier>Boundaries</ows:Identifier>
-                <LayerRef>coastlines</LayerRef>
-                <LayerRef>politicalBoundaries</LayerRef>
-                <LayerRef>depthContours</LayerRef>
-            </Theme>
-            <Theme>
-                <ows:Title>Transportation</ows:Title>
-                <ows:Identifier>Transportation</ows:Identifier>
-                <LayerRef>roads</LayerRef>
-                <LayerRef>railroads</LayerRef>
-                <LayerRef>airports</LayerRef>
-            </Theme>
-        </Theme>
-        <Theme>
-            <ows:Title>World Geology</ows:Title>
-            <ows:Identifier>World Geology</ows:Identifier>
-            <LayerRef>worldAgeRockType</LayerRef>
-            <LayerRef>worldFaultLines</LayerRef>
-            <LayerRef>felsicMagmatic</LayerRef>
-            <LayerRef>maficMagmatic</LayerRef>
-        </Theme>
-    </Themes>
-</Capabilities>
---></div>
-</body>
-</html>

Copied: sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html (from rev 10919, trunk/openlayers/tests/Format/WMTSCapabilities/v1_0_0.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/WMTSCapabilities/v1_0_0.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,323 @@
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+
+        function test_ows(t) {
+            t.plan(17);
+            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+            var doc = new OpenLayers.Format.XML().read(xml);
+            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+            // ows:ServiceIdentification
+            var serviceIdentification = obj.serviceIdentification;
+            t.eq(serviceIdentification.title, "Web Map Tile Service", "ows:ServiceIdentification title is correct");
+            t.eq(serviceIdentification.serviceTypeVersion, "1.0.0", "ows:ServiceIdentification serviceTypeVersion is correct");
+            t.eq(serviceIdentification.serviceType.value, "OGC WMTS", "ows:ServiceIdentification serviceType is correct");
+
+            // ows:ServiceProvider
+            var serviceProvider = obj.serviceProvider;
+            t.eq(serviceProvider.providerName, "MiraMon", "ows:ServiceProvider providerName is correct");
+            t.eq(serviceProvider.providerSite, "http://www.creaf.uab.es/miramon", "ows:ServiceProvider providerSite is correct");
+            t.eq(serviceProvider.serviceContact.individualName, "Joan Maso Pau", "ows:ServiceProvider individualName is correct");
+            t.eq(serviceProvider.serviceContact.positionName, "Senior Software Engineer", "ows:ServiceProvider positionName is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.administrativeArea, "Barcelona", "ows:ServiceProvider address administrativeArea is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.city, "Bellaterra", "ows:ServiceProvider address city is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.country, "Spain", "ows:ServiceProvider address country is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.deliveryPoint, "Fac Ciencies UAB", "ows:ServiceProvider address deliveryPoint is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.electronicMailAddress, "joan.maso at uab.es", "ows:ServiceProvider address electronicMailAddress is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.address.postalCode, "08193", "ows:ServiceProvider address postalCode is correct");
+            t.eq(serviceProvider.serviceContact.contactInfo.phone.voice, "+34 93 581 1312", "ows:ServiceProvider phone voice is correct");
+
+            // ows:OperationsMetadata
+            var operationsMetadata = obj.operationsMetadata;
+            t.eq(operationsMetadata.GetCapabilities.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetCapabilities url is correct");
+            t.eq(operationsMetadata.GetFeatureInfo.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetFeatureInfo url is correct");
+            t.eq(operationsMetadata.GetTile.dcp.http.get, "http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?", "ows:OperationsMetadata GetTile url is correct");
+        }
+    
+        function test_layers(t) {
+            t.plan(21);
+            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+            var doc = new OpenLayers.Format.XML().read(xml);
+    
+            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+            var contents = obj.contents;
+    
+            var numOfLayers = contents.layers.length;
+            t.eq(numOfLayers, 1, "correct count of layers");
+
+            var layer = contents.layers[0];
+            t.eq(layer.abstract, "Coastline/shorelines (BA010)", "layer abstract is correct");
+            t.eq(layer.identifier, "coastlines", "layer identifier is correct");
+            t.eq(layer.title, "Coastlines", "layer title is correct");
+
+            var numOfFormats = layer.formats.length;
+            t.eq(numOfFormats, 2, "correct count of formats");
+            t.eq(layer.formats[0], "image/png", "format image/png is correct");
+            t.eq(layer.formats[1], "image/gif", "format image/gif is correct");
+
+            var numOfStyles = layer.styles.length;
+            t.eq(numOfStyles, 2, "correct count of styles");
+            t.eq(layer.styles[0].identifier, "DarkBlue", "style 0 identifier is correct");
+            t.eq(layer.styles[0].isDefault, true, "style 0 isDefault is correct");
+            t.eq(layer.styles[0].title, "Dark Blue", "style 0 title is correct");
+            t.eq(layer.styles[1].identifier, "thickAndRed", "style 1 identifier is correct");
+            t.ok(!layer.styles[1].isDefault, "style 1 isDefault is correct");
+            t.eq(layer.styles[1].title, "Thick And Red", "style 1 title is correct");
+            //t.eq(layer.styles[1].abstract, "Specify this style if you want your maps to have thick red coastlines. ", "style 1 abstract is correct");
+
+            t.eq(layer.tileMatrixSetLinks.length, 1, "correct count of tileMatrixSetLinks");
+            t.eq(layer.tileMatrixSetLinks[0].tileMatrixSet, "BigWorld", "tileMatrixSet is correct");
+
+            var wgs84Bbox = layer.bounds;
+            t.ok(wgs84Bbox instanceof OpenLayers.Bounds, "wgs84BoudingBox instance of OpenLayers.Bounds");
+            t.eq(wgs84Bbox.left, -180.0, "wgs84BoudingBox left is correct");
+            t.eq(wgs84Bbox.right, 180.0, "wgs84BoudingBox right is correct");
+            t.eq(wgs84Bbox.bottom, -90.0, "wgs84BoudingBox bottom is correct");
+            t.eq(wgs84Bbox.top, 90.0, "wgs84BoudingBox top is correct");
+            
+        }
+
+        function test_tileMatrixSets(t) {
+            t.plan(19);
+            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+            var doc = new OpenLayers.Format.XML().read(xml);
+    
+            var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+
+            var tileMatrixSets = obj.contents.tileMatrixSets;
+            t.ok(tileMatrixSets['BigWorld'], "tileMatrixSets 'BigWorld' found");
+            var bigWorld = tileMatrixSets['BigWorld'];
+            t.eq(bigWorld.identifier, "BigWorld", "tileMatrixSets identifier is correct");
+            t.eq(bigWorld.matrixIds.length, 2, "tileMatrix count is correct");
+            t.eq(bigWorld.matrixIds[0].identifier, "1e6", "tileMatrix 0 identifier is correct");
+            t.eq(bigWorld.matrixIds[0].matrixHeight, 50000, "tileMatrix 0 matrixHeight is correct");
+            t.eq(bigWorld.matrixIds[0].matrixWidth, 60000, "tileMatrix 0 matrixWidth is correct");
+            t.eq(bigWorld.matrixIds[0].scaleDenominator, 1000000, "tileMatrix 0 scaleDenominator is correct");
+            t.eq(bigWorld.matrixIds[0].tileWidth, 256, "tileMatrix 0 tileWidth is correct");
+            t.eq(bigWorld.matrixIds[0].tileHeight, 256, "tileMatrix 0 tileHeight is correct");
+            t.eq(bigWorld.matrixIds[0].topLeftCorner.lon, -180, "tileMatrix 0 topLeftCorner.lon is correct");
+            t.eq(bigWorld.matrixIds[0].topLeftCorner.lat, 84, "tileMatrix 0 topLeftCorner.lat is correct");
+
+            t.eq(bigWorld.matrixIds[1].identifier, "2.5e6", "tileMatrix 1 identifier is correct");
+            t.eq(bigWorld.matrixIds[1].matrixHeight, 7000, "tileMatrix 1 matrixHeight is correct");
+            t.eq(bigWorld.matrixIds[1].matrixWidth, 9000, "tileMatrix 1 matrixWidth is correct");
+            t.eq(bigWorld.matrixIds[1].scaleDenominator, 2500000, "tileMatrix 1 scaleDenominator is correct");
+            t.eq(bigWorld.matrixIds[1].tileWidth, 256, "tileMatrix 1 tileWidth is correct");
+            t.eq(bigWorld.matrixIds[1].tileHeight, 256, "tileMatrix 1 tileHeight is correct");
+            t.eq(bigWorld.matrixIds[1].topLeftCorner.lon, -180, "tileMatrix 1 topLeftCorner.lon is correct");
+            t.eq(bigWorld.matrixIds[1].topLeftCorner.lat, 84, "tileMatrix 1 topLeftCorner.lat is correct");
+        }
+        
+        function test_createLayer(t) {
+            t.plan(6);
+            
+            var format = new OpenLayers.Format.WMTSCapabilities();
+
+            var xml = document.getElementById("ogcsample").firstChild.nodeValue;
+            var doc = new OpenLayers.Format.XML().read(xml);
+    
+            var caps = format.read(doc);
+            var layer;
+            
+            var success = true;
+            try {
+                // incomplete config (missing matrixSet)
+                layer = format.createLayer(caps, {
+                    layer: "coastlines"
+                });
+            } catch (err) {
+                success = false;
+            }
+            t.ok(!success, "createLayer throws error if provided incomplete layer config");
+            
+            // bogus layer identifier
+            layer = format.createLayer(caps, {
+                layer: "foo",
+                matrixSet: "BigWorld"
+            });
+            t.eq(layer, undefined, "createLayer returns undefined given bad layer identifier");
+            
+            // bogus matrixSet identifier
+            layer = format.createLayer(caps, {
+                layer: "coastlines",
+                matrixSet: "TheWorld"
+            });
+            t.eq(layer, undefined, "createLayer returns undefined given bad matrixSet identifier");
+            
+            layer = format.createLayer(caps, {
+                layer: "coastlines",
+                matrixSet: "BigWorld"
+            });
+            t.ok(layer instanceof OpenLayers.Layer.WMTS, "correct instance");
+            
+            t.eq(layer.matrixIds.length, 2, "correct matrixIds length");
+            t.eq(layer.name, "Coastlines", "correct layer title");
+            
+        }
+        
+    </script>
+</head>
+<body>
+
+<!--
+OGC example below taken from
+http://schemas.opengis.net/wmts/1.0/examples/wmtsGetCapabilities_response.xml
+-->
+<div id="ogcsample"><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
+    <ows:ServiceIdentification>
+        <ows:Title>Web Map Tile Service</ows:Title>
+        <ows:Abstract>Service that contrains the map access interface to some TileMatrixSets</ows:Abstract>
+        <ows:Keywords>
+            <ows:Keyword>tile</ows:Keyword>
+            <ows:Keyword>tile matrix set</ows:Keyword>
+            <ows:Keyword>map</ows:Keyword>
+        </ows:Keywords>
+        <ows:ServiceType>OGC WMTS</ows:ServiceType>
+        <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
+        <ows:Fees>none</ows:Fees>
+        <ows:AccessConstraints>none</ows:AccessConstraints>
+    </ows:ServiceIdentification>
+    <ows:ServiceProvider>
+        <ows:ProviderName>MiraMon</ows:ProviderName>
+        <ows:ProviderSite xlink:href="http://www.creaf.uab.es/miramon"/>
+        <ows:ServiceContact>
+            <ows:IndividualName>Joan Maso Pau</ows:IndividualName>
+            <ows:PositionName>Senior Software Engineer</ows:PositionName>
+            <ows:ContactInfo>
+                <ows:Phone>
+                    <ows:Voice>+34 93 581 1312</ows:Voice>
+                    <ows:Facsimile>+34 93 581 4151</ows:Facsimile>
+                </ows:Phone>
+                <ows:Address>
+                    <ows:DeliveryPoint>Fac Ciencies UAB</ows:DeliveryPoint>
+                    <ows:City>Bellaterra</ows:City>
+                    <ows:AdministrativeArea>Barcelona</ows:AdministrativeArea>
+                    <ows:PostalCode>08193</ows:PostalCode>
+                    <ows:Country>Spain</ows:Country>
+                    <ows:ElectronicMailAddress>joan.maso at uab.es</ows:ElectronicMailAddress>
+                </ows:Address>
+            </ows:ContactInfo>
+        </ows:ServiceContact>
+    </ows:ServiceProvider>
+    <ows:OperationsMetadata>
+        <ows:Operation name="GetCapabilities">
+            <ows:DCP>
+                <ows:HTTP>
+                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?">
+                        <ows:Constraint name="GetEncoding">
+                            <ows:AllowedValues>
+                                <ows:Value>KVP</ows:Value>
+                            </ows:AllowedValues>
+                        </ows:Constraint>
+                    </ows:Get>
+                </ows:HTTP>
+            </ows:DCP>
+        </ows:Operation>
+        <ows:Operation name="GetTile">
+            <ows:DCP>
+                <ows:HTTP>
+                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?"/>
+                </ows:HTTP>
+            </ows:DCP>
+        </ows:Operation>
+        <ows:Operation name="GetFeatureInfo">
+            <ows:DCP>
+                <ows:HTTP>
+                    <ows:Get xlink:href="http://www.miramon.uab.es/cgi-bin/MiraMon5_0.cgi?"/>
+                </ows:HTTP>
+            </ows:DCP>
+        </ows:Operation>
+    </ows:OperationsMetadata>
+    <Contents>
+        <Layer>
+            <ows:Title>Coastlines</ows:Title>
+            <ows:Abstract>Coastline/shorelines (BA010)</ows:Abstract>
+            <ows:WGS84BoundingBox>
+                <ows:LowerCorner>-180 -90</ows:LowerCorner>
+                <ows:UpperCorner>180 90</ows:UpperCorner>
+            </ows:WGS84BoundingBox>
+            <ows:Identifier>coastlines</ows:Identifier>
+            <Style isDefault="true">
+                <ows:Title>Dark Blue</ows:Title>
+                <ows:Identifier>DarkBlue</ows:Identifier>
+                <LegendURL format="image/png" xlink:href="http://www.miramon.uab.es/wmts/Coastlines/coastlines_darkBlue.png"/>
+            </Style>
+            <Style>
+                <ows:Title>Thick And Red</ows:Title>
+                <ows:Abstract>Specify this style if you want your maps to have thick red coastlines.
+                </ows:Abstract>
+                <ows:Identifier>thickAndRed</ows:Identifier>
+            </Style>
+            <Format>image/png</Format>
+            <Format>image/gif</Format>
+            <Dimension>
+                <ows:Title>Time</ows:Title>
+                <ows:Abstract>Monthly datasets</ows:Abstract>
+                <ows:Identifier>TIME</ows:Identifier>
+                <Value>2007-05</Value>
+                <Value>2007-06</Value>
+                <Value>2007-07</Value>
+            </Dimension>
+            <TileMatrixSetLink>
+                <TileMatrixSet>BigWorld</TileMatrixSet>
+            </TileMatrixSetLink>
+        </Layer>
+        <TileMatrixSet>        
+            <ows:Identifier>BigWorld</ows:Identifier>
+            <ows:SupportedCRS>urn:ogc:def:crs:OGC:1.3:CRS84</ows:SupportedCRS>
+            <TileMatrix>
+                <ows:Identifier>1e6</ows:Identifier>
+                <ScaleDenominator>1e6</ScaleDenominator>        
+                <TopLeftCorner>-180 84</TopLeftCorner>        
+                <TileWidth>256</TileWidth>
+                <TileHeight>256</TileHeight>        
+                <MatrixWidth>60000</MatrixWidth>
+                <MatrixHeight>50000</MatrixHeight>
+            </TileMatrix>
+            <TileMatrix>
+                <ows:Identifier>2.5e6</ows:Identifier>
+                <ScaleDenominator>2.5e6</ScaleDenominator>
+                <TopLeftCorner>-180 84</TopLeftCorner>
+                <TileWidth>256</TileWidth>
+                <TileHeight>256</TileHeight>
+                <MatrixWidth>9000</MatrixWidth>
+                <MatrixHeight>7000</MatrixHeight>
+            </TileMatrix>
+        </TileMatrixSet>
+    </Contents>
+    <Themes>
+        <Theme>
+            <ows:Title>Foundation</ows:Title>
+            <ows:Abstract>"Digital Chart Of The World" data</ows:Abstract>
+            <ows:Identifier>Foundation</ows:Identifier>
+            <Theme>
+                <ows:Title>Boundaries</ows:Title>
+                <ows:Identifier>Boundaries</ows:Identifier>
+                <LayerRef>coastlines</LayerRef>
+                <LayerRef>politicalBoundaries</LayerRef>
+                <LayerRef>depthContours</LayerRef>
+            </Theme>
+            <Theme>
+                <ows:Title>Transportation</ows:Title>
+                <ows:Identifier>Transportation</ows:Identifier>
+                <LayerRef>roads</LayerRef>
+                <LayerRef>railroads</LayerRef>
+                <LayerRef>airports</LayerRef>
+            </Theme>
+        </Theme>
+        <Theme>
+            <ows:Title>World Geology</ows:Title>
+            <ows:Identifier>World Geology</ows:Identifier>
+            <LayerRef>worldAgeRockType</LayerRef>
+            <LayerRef>worldFaultLines</LayerRef>
+            <LayerRef>felsicMagmatic</LayerRef>
+            <LayerRef>maficMagmatic</LayerRef>
+        </Theme>
+    </Themes>
+</Capabilities>
+--></div>
+</body>
+</html>

Copied: sandbox/ahocevar/playground/tests/Format/WMTSCapabilities.html (from rev 10919, trunk/openlayers/tests/Format/WMTSCapabilities.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Format/WMTSCapabilities.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Format/WMTSCapabilities.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,20 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+    
+    function test_initialize(t) {
+        
+        t.plan(1);
+        var format = new OpenLayers.Format.WMTSCapabilities({
+            version: "foo"
+        });
+        t.eq(format.version, "foo", "version set on format");
+        
+    }
+    
+    </script> 
+</head> 
+<body>
+</body> 
+</html> 

Modified: sandbox/ahocevar/playground/tests/Format/XML.html
===================================================================
--- sandbox/ahocevar/playground/tests/Format/XML.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Format/XML.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -167,18 +167,38 @@
     }
 
     function test_Format_XML_createTextNode(t) {
-        t.plan(4);
+        t.plan(10);
 
         var format = new OpenLayers.Format.XML();
-        var value = Math.random().toString();
-        var node = format.createTextNode(value);
+        var value, node;
+
+        value = "string";
+        node = format.createTextNode(value);
         t.eq(node.nodeType, 3,
-             "node has correct type");
+             "[string] node has correct type");
         t.eq(node.nodeName, "#text",
-             "node has correct name");
-        t.eq(node.nodeValue, value,
-             "node has correct value");
+             "[string] node has correct name");
+        t.eq(node.nodeValue, "string",
+             "[string] node has correct value");
         
+        value = 0.42;
+        node = format.createTextNode(value);
+        t.eq(node.nodeType, 3,
+             "[number] node has correct type");
+        t.eq(node.nodeName, "#text",
+             "[number] node has correct name");
+        t.eq(node.nodeValue, "0.42",
+             "[number] node has correct value");
+
+        value = false;
+        node = format.createTextNode(value);
+        t.eq(node.nodeType, 3,
+             "[boolean] node has correct type");
+        t.eq(node.nodeName, "#text",
+             "[boolean] node has correct name");
+        t.eq(node.nodeValue, "false",
+             "[boolean] node has correct value");
+
         var doc = format.read(text);
         if (doc.importNode) {
             node = doc.importNode(node, true);
@@ -596,6 +616,10 @@
                 node: format.createElementNSPlus("foo:bar", {value: 0}),
                 expect: "<foo:bar xmlns:foo='http://example.com/foo'>0</foo:bar>"
             }, {
+                description: "value of 0.42 gets appended as a text node",
+                node: format.createElementNSPlus("foo:bar", {value: 0.42}),
+                expect: "<foo:bar xmlns:foo='http://example.com/foo'>0.42</foo:bar>"
+            }, {
                 description: "value of true gets appended as a text node",
                 node: format.createElementNSPlus("foo:bar", {value: true}),
                 expect: "<foo:bar xmlns:foo='http://example.com/foo'>true</foo:bar>"

Modified: sandbox/ahocevar/playground/tests/Geometry/Collection.html
===================================================================
--- sandbox/ahocevar/playground/tests/Geometry/Collection.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Geometry/Collection.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -250,19 +250,163 @@
         t.eq(multipoint.bounds, null, "multipoint component bounds cleared");
 
     }
+
+    function test_getCentroid_pts_only(t) {
+        t.plan(3);
+
+        coll = new OpenLayers.Geometry.Collection();
+        coll.addComponent(new OpenLayers.Geometry.Point(0,0));
+        coll.addComponent(new OpenLayers.Geometry.Point(1,1));
+
+        centroid = coll.getCentroid(true);
+        t.ok(centroid != null, 'The centroid is not null.');
+        t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
+        t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
+
+        coll.destroy();
+    }
+
+    function test_getCentroid_poly_nonrecursive(t) {
+        t.plan(3);
+
+        coll = new OpenLayers.Geometry.Collection();
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(0,0),
+                    new OpenLayers.Geometry.Point(0,1),
+                    new OpenLayers.Geometry.Point(1,1),
+                    new OpenLayers.Geometry.Point(1,0)
+                ])
+            ])
+        );
+        // performing non-recursive getCentroid means this next polygon
+        // is excluded from the centroid computation
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(2,2),
+                    new OpenLayers.Geometry.Point(2,3),
+                    new OpenLayers.Geometry.Point(3,3),
+                    new OpenLayers.Geometry.Point(3,2)
+                ])
+            ])
+        );
+
+        centroid = coll.getCentroid();
+        t.ok(centroid != null, 'The centroid is not null.');
+        t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
+        t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
+
+        coll.destroy();
+    }
+
+    function test_getCentroid_poly_only(t) {
+        t.plan(3);
+
+        coll = new OpenLayers.Geometry.Collection();
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                    new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(0,0),
+                    new OpenLayers.Geometry.Point(0,1),
+                    new OpenLayers.Geometry.Point(1,1),
+                    new OpenLayers.Geometry.Point(1,0)
+                ])
+            ])
+        );
+
+        centroid = coll.getCentroid(true);
+        t.ok(centroid != null, 'The centroid is not null.');
+        t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
+        t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
+
+        coll.destroy();
+    }
+
+    function test_getCentroid_poly_and_pts(t) {
+        t.plan(3);
+
+        coll = new OpenLayers.Geometry.Collection();
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(0,0),
+                    new OpenLayers.Geometry.Point(0,1),
+                    new OpenLayers.Geometry.Point(1,1),
+                    new OpenLayers.Geometry.Point(1,0)
+                ])
+            ])
+        );
+
+        // since the polygon above has an area of 1 and these
+        // points have an area of 0, they should not change the centroid
+        coll.addComponent( new OpenLayers.Geometry.Point(2,2) );
+        coll.addComponent( new OpenLayers.Geometry.Point(4,4) );
+
+        centroid = coll.getCentroid(true);
+        t.ok(centroid != null, 'The centroid is not null.');
+        t.eq(centroid.x, 0.5, 'The centroid x coordinate is good.');
+        t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
+
+        coll.destroy();
+    }
+
+    function test_getCentroid_poly_big_and_small(t) {
+        t.plan(3);
+
+        coll = new OpenLayers.Geometry.Collection();
+        // polygon w/area=1, centroid=0.5,0.5
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(0,0),
+                    new OpenLayers.Geometry.Point(0,1),
+                    new OpenLayers.Geometry.Point(1,1),
+                    new OpenLayers.Geometry.Point(1,0)
+                ])
+            ])
+        );
+
+        // since the polygon above has an area of 1 and this
+        // polygon has an area of 4, the center is weighted 20% toward
+        // the first polygon
+
+        // polygon w/area=4, centroid=5.5,5.5
+        coll.addComponent(
+            new OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(4.5,-0.5),
+                    new OpenLayers.Geometry.Point(4.5,1.5),
+                    new OpenLayers.Geometry.Point(6.5,1.5),
+                    new OpenLayers.Geometry.Point(6.5,-0.5)
+                ])
+            ])
+        );
+
+        centroid = coll.getCentroid(true);
+        t.ok(centroid != null, 'The centroid is not null.');
+        t.eq(centroid.x, 4.5, 'The centroid x coordinate is good.');
+        t.eq(centroid.y, 0.5, 'The centroid y coordinate is good.');
+
+        coll.destroy();
+    }
+
     
     function test_Collection_destroy(t) {
-        t.plan( 1 );
+        t.plan( 3 );
         coll = new OpenLayers.Geometry.Collection();
-        coll.components = {};
-        
+        coll.addComponents(new OpenLayers.Geometry.Point(0,0));
+        coll.addComponents(new OpenLayers.Geometry.Point(10,10));
+        coll.getBounds();
         coll.destroy(); 
         
         t.ok(coll.components == null, "components array cleared");
+        t.ok(coll.getBounds() == null, "bounds is cleared");
+        t.ok(coll.id == null, "id is cleared");
 
     }
 
-
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Geometry/LinearRing.html
===================================================================
--- sandbox/ahocevar/playground/tests/Geometry/LinearRing.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Geometry/LinearRing.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -112,7 +112,24 @@
         var ring = new OpenLayers.Geometry.LinearRing(components);
         t.eq(ring.getLength(), 40, "getLength returns the correct perimiter");
     }
-    
+
+    function test_LinearRing_getCentroid(t) {
+        t.plan(2);
+        var components = [
+            new OpenLayers.Geometry.Point(0,0), 
+            new OpenLayers.Geometry.Point(0,10),
+            new OpenLayers.Geometry.Point(10,10), 
+            new OpenLayers.Geometry.Point(10,0)
+        ];
+        var ring = new OpenLayers.Geometry.LinearRing(components);
+        var centroid = ring.getCentroid();
+        t.ok(centroid.x === 5 && centroid.y === 5, "getCentroid returns the correct centroid");
+        ring.destroy();
+
+        ring = new OpenLayers.Geometry.LinearRing();
+        t.eq(ring.getCentroid(), null, "getCentroid returns null if no components");     
+    }
+
     function test_LinearRing_move(t) {
 
         var nvert = 4,

Modified: sandbox/ahocevar/playground/tests/Geometry.html
===================================================================
--- sandbox/ahocevar/playground/tests/Geometry.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Geometry.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -288,7 +288,7 @@
             wkt: "POINT(1 2)",
             geom: new OpenLayers.Geometry.Point(1, 2)
         }, {
-            wkt: "MULTIPOINT(3.5 5.6,4.8 10.5)",
+            wkt: "MULTIPOINT((3.5 5.6),(4.8 10.5))",
             geom: new OpenLayers.Geometry.MultiPoint([
                 new OpenLayers.Geometry.Point(3.5, 5.6),
                 new OpenLayers.Geometry.Point(4.8, 10.5)

Modified: sandbox/ahocevar/playground/tests/Handler/Drag.html
===================================================================
--- sandbox/ahocevar/playground/tests/Handler/Drag.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Handler/Drag.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -289,7 +289,7 @@
     }
 
     function test_Handler_Drag_submethods(t) {
-        t.plan(4);
+        t.plan(8);
         
         var map = new OpenLayers.Map('map', {controls: []});
 
@@ -300,6 +300,11 @@
         var handler = new OpenLayers.Handler.Drag(control, {});
         // set test events
         var events = ["down", "move", "up", "out"];
+        var onselect = {
+            "move": OpenLayers.Function.False,
+            "up": OpenLayers.Function.False,
+            "out": OpenLayers.Function.True
+        }
         var testEvents = {};
         var type, px;
         for(var i=0; i<events.length; ++i) {
@@ -313,10 +318,14 @@
                 t.ok(evt.xy.x == testEvents[type].xy.x &&
                      evt.xy.y == testEvents[type].xy.y,
                      "handler." + type + " called with the right event");
+                onselect[type] && t.ok(document.onselectstart === onselect[type], "document.onselectstart listener is correct after " + type);
             }
         }
         handler.activate();
         
+        // pretend that we have gone through a down-move-up-out cycle before
+        handler.oldOnselectstart = OpenLayers.Function.True;
+        
         // test mousedown
         handler.checkModifiers = function(evt) {
             return true;
@@ -343,6 +352,8 @@
         map.events.triggerEvent("mouseout", testEvents.out);
         OpenLayers.Util.mouseLeft = oldMouseLeft;
         
+        t.ok(document.onselectstart === OpenLayers.Function.True, "document.onselectstart listener correct after down-move-up-out cycle");
+        
     }
 
     function test_Handler_Drag_deactivate(t) {

Modified: sandbox/ahocevar/playground/tests/Handler/MouseWheel.html
===================================================================
--- sandbox/ahocevar/playground/tests/Handler/MouseWheel.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Handler/MouseWheel.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -62,12 +62,19 @@
     }    
     
     function test_Handler_MouseWheel_events(t) {
-        t.plan(5);
+        t.plan(6);
         
         var map = new OpenLayers.Map('map');
+        map.addLayer(new OpenLayers.Layer.WMS("","",{}));
+        map.zoomToMaxExtent();
         var control = new OpenLayers.Control();
         map.addControl(control);
-        var handler = new OpenLayers.Handler.MouseWheel(control);
+        var deltaZ;
+        var handler = new OpenLayers.Handler.MouseWheel(control, {
+            'up': function(evt, delta){
+                deltaZ = delta;
+            }
+        }, {interval: 200});
 
         // list below events that should be handled (events) and those
         // that should not be handled (nonevents) by the handler
@@ -99,7 +106,46 @@
         }
 
         var activated = handler.activate();
+        
+        var delta = 120;
+        if (window.opera && window.opera.version() < 9.2)  delta = -delta;
+        handler.onWheelEvent({'target':map.layers[0].div, wheelDelta: delta});
+        handler.onWheelEvent({'target':map.layers[0].div, wheelDelta: delta});
+        t.delay_call(1, function() {
+            t.eq(deltaZ, 2, "Multiple scroll actions triggered one event when interval is set");
+        });
+    }
 
+    function test_Handler_MouseWheel_cumulative(t) {
+        t.plan(1);
+
+        var deltaUp = 0;
+        var callbacks = {
+            up: function(evt, delta) {
+                deltaUp += delta;
+            }
+        };
+
+        var map = new OpenLayers.Map('map');
+        map.addLayer(new OpenLayers.Layer.WMS("","",{}));
+        map.zoomToMaxExtent();
+        var control = new OpenLayers.Control({});
+        map.addControl(control);
+        var handler = new OpenLayers.Handler.MouseWheel(control, callbacks, {
+            interval: 150,
+            cumulative: false    
+        });
+
+        var delta = 120;
+        // generate 20 scroll up in non cumulative mode
+        if (window.opera && window.opera.version() < 9.2)  delta = -delta;
+        for (var i=0; i < 20; i++) {
+            handler.onWheelEvent({'target':map.layers[0].div, wheelDelta: delta});
+        }
+        
+        t.delay_call(1, function() {
+            t.eq(deltaUp, 1, "Non cumulative mode works");
+        });
     }
 
     function test_Handler_MouseWheel_deactivate(t) {

Modified: sandbox/ahocevar/playground/tests/Handler/Polygon.html
===================================================================
--- sandbox/ahocevar/playground/tests/Handler/Polygon.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Handler/Polygon.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -158,6 +158,187 @@
         map.destroy();
     }        
 
+    function test_rings(t) {
+        t.plan(12);
+
+        var log = [];
+        var map = new OpenLayers.Map({
+            div: "map",
+            resolutions: [1],
+            maxExtent: new OpenLayers.Bounds(-10, -10, 10, 10),
+            layers: [
+                new OpenLayers.Layer.Vector(null, {
+                    isBaseLayer: true,
+                    eventListeners: {
+                        featureadded: function(event) {
+                            log.push(event);
+                        },
+                        sketchmodified: function(event) {
+                            log.push(event);
+                        },
+                        sketchcomplete: function(event) {
+                            log.push(event);
+                        }
+                    }
+                })
+            ],
+            center: new OpenLayers.LonLat(0, 0),
+            zoom: 0
+        });
+        
+        // create control for drawing polygons with holes
+        var draw = new OpenLayers.Control.DrawFeature(
+            map.layers[0],
+            OpenLayers.Handler.Polygon,
+            {handlerOptions: {holeModifier: "altKey"}}
+        );
+        map.addControl(draw);
+        draw.activate();
+        
+        var event;
+        function trigger(type, event) {
+            map.events.triggerEvent(type, OpenLayers.Util.extend({}, event));
+        }
+        
+        // a) draw a polygon
+        log = [];
+        // start at -9, 9
+        event = {xy: new OpenLayers.Pixel(-9, 9)};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -1, 9
+        event = {xy: new OpenLayers.Pixel(-1, 9)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -1, 1
+        event = {xy: new OpenLayers.Pixel(-1, 1)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -9, 1
+        event = {xy: new OpenLayers.Pixel(-9, 1)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // finish
+        event = {xy: new OpenLayers.Pixel(-9, 1)};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        trigger("dblclick", event);
+        
+        // make assertions
+        t.eq(log.length, 9, "a) correct number of events");
+        t.eq(log[log.length-1].type, "featureadded", "a) featureadded event last");
+        t.eq(log[log.length-1].feature.geometry.getArea(), 64, "a) correct polygon area");
+
+        // b) draw a hole
+        log = [];
+        // start at -6, 6
+        event = {xy: new OpenLayers.Pixel(-6, 6), altKey: true};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -3, 6
+        event = {xy: new OpenLayers.Pixel(-3, 6), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -3, 3
+        event = {xy: new OpenLayers.Pixel(-3, 3), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -6, 3
+        event = {xy: new OpenLayers.Pixel(-6, 3), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // finish
+        event = {xy: new OpenLayers.Pixel(-6, 3), altKey: true};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        trigger("dblclick", event);
+        
+        // make assertions
+        t.eq(log.length, 8, "b) correct number of events");
+        t.eq(log[log.length-1].type, "sketchcomplete", "b) sketchcomplete event last");
+        t.eq(log[log.length-1].feature.geometry.getArea(), 55, "b) correct polygon area");
+        
+
+        // c) draw a polygon that overlaps the first
+        log = [];
+        // start at -2, 2
+        event = {xy: new OpenLayers.Pixel(-2, 2)};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to 2, 2
+        event = {xy: new OpenLayers.Pixel(2, 2)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to 2, -2
+        event = {xy: new OpenLayers.Pixel(2, -2)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -2, -2
+        event = {xy: new OpenLayers.Pixel(-2, -2)};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // finish
+        event = {xy: new OpenLayers.Pixel(-2, -2)};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        trigger("dblclick", event);
+        
+        // make assertions
+        t.eq(log.length, 9, "c) correct number of events");
+        t.eq(log[log.length-1].type, "featureadded", "c) featureadded event last");
+        t.eq(log[log.length-1].feature.geometry.getArea(), 16, "c) correct polygon area");
+
+        // d) draw a hole that tries to go outside the exterior ring
+        log = [];
+        // start at -1, 1
+        event = {xy: new OpenLayers.Pixel(-1, 1), altKey: true};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to 1, 1
+        event = {xy: new OpenLayers.Pixel(1, 1), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // try to draw to -8, 8 (ouside active polygon)
+        event = {xy: new OpenLayers.Pixel(-8, 8), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to 1, -1
+        event = {xy: new OpenLayers.Pixel(1, -1), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // draw to -1, -1
+        event = {xy: new OpenLayers.Pixel(-1, -1), altKey: true};
+        trigger("mousemove", event);
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        // finish
+        event = {xy: new OpenLayers.Pixel(-1, 1), altKey: true};
+        trigger("mousedown", event);
+        trigger("mouseup", event);
+        trigger("dblclick", event);
+        
+        // make assertions
+        t.eq(log.length, 11, "d) correct number of events");
+        t.eq(log[log.length-1].type, "sketchcomplete", "d) sketchcomplete event last");
+        t.eq(log[log.length-1].feature.geometry.getArea(), 12, "d) correct polygon area");
+        
+        
+        map.destroy();
+    }        
+
+
     function test_Handler_Polygon_destroy(t) {
         t.plan(8);
         var map = new OpenLayers.Map('map');

Modified: sandbox/ahocevar/playground/tests/Layer/ArcGIS93Rest.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/ArcGIS93Rest.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/ArcGIS93Rest.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -229,10 +229,10 @@
         var tile = layer.grid[0][0];
         var request = layer.getURL(tile.bounds);
         var args = OpenLayers.Util.getParameters(request);
-        t.eq(parseInt(args['SIZE'].split(",")[0]),
+        t.eq(parseInt(args['SIZE'][0]),
              tile.size.w,
              "layer without gutter requests images that are as wide as the tile");
-        t.eq(parseInt(args['SIZE'].split(",")[1]),
+        t.eq(parseInt(args['SIZE'][1]),
              tile.size.h,
              "layer without gutter requests images that are as tall as the tile");
         
@@ -251,10 +251,10 @@
         var tile = layer.grid[0][0];
         var request = layer.getURL(tile.bounds);
         var args = OpenLayers.Util.getParameters(request);
-        t.eq(parseInt(args['SIZE'].split(",")[0]),
+        t.eq(parseInt(args['SIZE'][0]),
              tile.size.w + (2 * gutter),
              "layer with gutter requests images that are wider by twice the gutter");
-        t.eq(parseInt(args['SIZE'].split(",")[1]),
+        t.eq(parseInt(args['SIZE'][1]),
              tile.size.h + (2 * gutter),
              "layer with gutter requests images that are taller by twice the gutter");
 

Modified: sandbox/ahocevar/playground/tests/Layer/ArcIMS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/ArcIMS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/ArcIMS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -83,7 +83,41 @@
         t.eq( typeof layer.options.layers[0].query.where, "string", "where query is a string" );
         t.eq( layer.options.layers[0].query.where, querydef.where, "where query matches" );
       }
+      function test_Layer_ArcIMS_clone (t) {
+          t.plan(5);
+  
+          var url = imsUrl;
+          var options = {
+            serviceName: serviceName,
+            async: false,
+            displayOutsideMaxExtent: true
+          };
+          var map = new OpenLayers.Map('map', {controls: []});
+          var layer = new OpenLayers.Layer.ArcIMS(name, url, options);
+          map.addLayer(layer);
+  
+          layer.grid = [ [6, 7],
+                         [8, 9]];
+  
+          var clone = layer.clone();
+  
+          t.ok( clone.grid != layer.grid, "clone does not copy grid");
+  
+          t.ok( clone.tileSize.equals(layer.tileSize), "tileSize correctly cloned");
+  
+          t.eq( clone.params.serviceName, layer.params.serviceName, "serviceName copied correctly");
+  
+          t.eq( clone.async, layer.async, "async copied correctly");
+  
+          t.eq( clone.url, layer.url, "url copied correctly");
+  
+          layer.grid = null;
+          map.destroy();
+      }
       
     </script>
   </head>
-</html>
\ No newline at end of file
+  <body>
+    <div id="map" style="width:500px;height:550px"></div> 
+  </body>  
+</html>

Modified: sandbox/ahocevar/playground/tests/Layer/EventPane.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/EventPane.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/EventPane.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -57,7 +57,7 @@
 // MOUSEMOVE test does not seem to work... 
 //         t.plan( 2 );    
 
-        if (OpenLayers.Util.getBrowserName() != "firefox" && OpenLayers.Util.getBrowserName() != "mozilla") {
+        if (OpenLayers.BROWSER_NAME != "firefox" && OpenLayers.BROWSER_NAME != "mozilla") {
           t.plan(4);
         } else {
           t.plan(0);
@@ -118,10 +118,48 @@
         layer.getWarningHTML = function() { this.warning = true; return ""; };
         map.addLayer(layer);
         map.removeLayer(layer);
-        t.eq(layer.pane, null, "Layer.pane is null after being removed.");
-   }      
+        var parent = layer.pane.parentNode;
+        // IE creates a DOCUMENT_FRAGMENT_NODE for the parent
+        t.ok(!parent || parent.nodeType == 11, "Layer.pane removed from dom.");
+    }
+   
+    function test_repeat_add(t) {
 
+        t.plan(1);
+        var map = new OpenLayers.Map("map");
+        
+        layer = new OpenLayers.Layer.EventPane();
+        layer.loadMapObject = function() {};
+        layer.getWarningHTML = function() {this.warning = true; return "";};
 
+        map.addLayer(layer);
+        map.removeLayer(layer);
+        
+        // try adding the layer a second time
+        var msg = "layer successfully added after being removed";
+        var pass = true;
+        try {
+            map.addLayer(layer);
+        } catch (err) {
+            msg = "couldn't add layer after removing: " + err;
+            pass = false;
+        }
+        t.ok(pass, msg);
+
+    }
+    
+    function test_destroy(t) {
+        
+        t.plan(2);
+        layer = new OpenLayers.Layer.EventPane();
+        t.ok(layer.pane, "pane created on initialize");
+        
+        layer.destroy();
+        t.ok(!layer.pane, "pane deleted on destroy");
+        
+    }
+
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Layer/GeoRSS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/GeoRSS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/GeoRSS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -172,7 +172,7 @@
         });
     }
     function test_Layer_GeoRSS_loadend_Event(t) {
-        var browserCode = OpenLayers.Util.getBrowserName();
+        var browserCode = OpenLayers.BROWSER_NAME;
         if (browserCode == "msie") {
             t.plan(1);
             t.ok(true, "IE fails the GeoRSS test. This could probably be fixed by someone with enough energy to fix it.");

Deleted: sandbox/ahocevar/playground/tests/Layer/Google/v3.html
===================================================================
--- trunk/openlayers/tests/Layer/Google/v3.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Google/v3.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,364 +0,0 @@
-<html>
-<head>
-    <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-    var layer; 
-                   
-    function test_Layer_Google_constructor (t) {
-        t.plan( 5 );
-        
-        var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.Google('Goog Layer');
-        map.addLayer(layer);
-        
-        
-        t.ok( layer instanceof OpenLayers.Layer.Google, "new OpenLayers.Layer.Google returns object" );
-        t.eq( layer.CLASS_NAME, "OpenLayers.Layer.Google", "CLASS_NAME variable set correctly");
-    
-        t.eq( layer.name, "Goog Layer", "layer.name is correct" );
-    
-        t.ok ( layer.mapObject != null, "GMap Object correctly loaded");
-        
-        t.eq(layer.version, "3", "API version 3 detected.");
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        var layer, clone;
-        
-        // test default layer
-        layer = new OpenLayers.Layer.Google();
-        clone = layer.clone();
-        t.ok(clone instanceof OpenLayers.Layer.Google, "[default] good instance");
-        
-        layer.destroy();
-        clone.destroy();
-        
-        // test with alt type
-        layer = new OpenLayers.Layer.Google(null, {type: google.maps.MapTypeId.SATELLITE});
-        clone = layer.clone();
-        t.ok(clone.type === google.maps.MapTypeId.SATELLITE, "[sat] correct type");
-        
-        layer.destroy();
-        clone.destroy();   
-    }
-    
-    function test_Layer_Google_isBaseLayer (t) {
-        t.plan(1);
-        
-        var layer = new OpenLayers.Layer.Google('Goog Layer');
-    
-        t.ok(layer.isBaseLayer, "a default load of google layer responds as a base layer");
-    }    
-    
-    function test_Layer_Google_Translation_lonlat (t) {
-        t.plan( 4 );
-        
-        var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.Google('Goog Layer');
-        map.addLayer(layer);
-    
-    // these two lines specify an appropriate translation. 
-    //  the code afterwards works by itself to test that translation
-    //  works correctly both ways.
-       var gLatLng = new google.maps.LatLng(50,100);
-       // v3 uses sphericalMercator by default
-       var correspondingOLLonLat = new OpenLayers.LonLat(100,50).transform(
-           new OpenLayers.Projection("EPSG:4326"),
-           map.getProjectionObject()
-       );
-    
-    
-       olLonLat = layer.getOLLonLatFromMapObjectLonLat(gLatLng);
-       t.ok(olLonLat.equals(correspondingOLLonLat), "Translation from GLatLng to OpenLayers.LonLat works");
-    
-       var transGLatLng = layer.getMapObjectLonLatFromOLLonLat(olLonLat);
-       t.ok( transGLatLng.equals(gLatLng), "Translation from OpenLayers.LonLat to GLatLng works");
-    
-       t.ok( layer.getMapObjectLonLatFromOLLonLat(null) == null, "getGLatLngFromOLLonLat(null) returns null");
-       t.ok( layer.getOLLonLatFromMapObjectLonLat(null) == null, "getOLLonLatFromGLatLng(null) returns null");
-    }
-    
-    function test_Layer_Google_Translation_pixel (t) {
-        t.plan( 4 );
-        
-        var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.Google('Goog Layer');
-        map.addLayer(layer);
-    
-     // these two lines specify an appropriate translation. 
-     //  the code afterwards works by itself to test that translation
-     //  works correctly both ways.
-        var gPoint = new google.maps.Point(50,100);
-        var correspondingOLPixel = new OpenLayers.Pixel(50, 100);
-    
-    
-        olPixel = layer.getOLPixelFromMapObjectPixel(gPoint);
-        t.ok( olPixel.equals(correspondingOLPixel), "Translation from GPoint to OpenLayers.Pixel works");
-    
-        var transGPoint = layer.getMapObjectPixelFromOLPixel(olPixel);
-        t.ok( transGPoint.equals(gPoint), "Translation from OpenLayers.Pixel to GPoint works");
-    
-        t.ok( layer.getMapObjectPixelFromOLPixel(null) == null, "getGPointFromOLPixel(null) returns null");
-        t.ok( layer.getOLPixelFromMapObjectPixel(null) == null, "getOLPixelFromGPoint(null) returns null");
-    }
-    
-    function test_Layer_destroy (t) {
-        t.plan( 5 );    
-    
-        var map = new OpenLayers.Map('map');
-        
-        layer = new OpenLayers.Layer.Google('Test Layer');
-        map.addLayer(layer);
-    
-        layer.destroy();
-    
-        t.eq( layer.name, null, "layer.name is null after destroy" );
-        t.eq( layer.div, null, "layer.div is null after destroy" );
-        t.eq( layer.map, null, "layer.map is null after destroy" );
-        t.eq( layer.options, null, "layer.options is null after destroy" );
-        t.eq( layer.gmap, null, "layer.gmap is null after destroy" );
-    }
-    
-    function test_Layer_Goole_forwardMercator(t){
-        t.plan(2);
-        //Just test that the fowardMercator function still exists.
-        var layer = new OpenLayers.Layer.Google('Test Layer', {'sphericalMercator': true});
-        layer.forwardMercator = function(evt) {
-            t.ok(true,
-                 "GoogleMercator.forwardMercator was called and executed." );
-            return;
-        }
-        layer.forwardMercator();
-        //Now test the fowardMercator returns the expected LonLat object
-        var layer = new OpenLayers.Layer.Google('Test Layer', {'sphericalMercator': true});
-        var lonlat2 = new OpenLayers.LonLat(Math.random(),Math.random());
-        var result = layer.forwardMercator(lonlat2.lon, lonlat2.lat);
-        t.ok(result instanceof OpenLayers.LonLat, "OpenLayers.Google.fowardMercator returns LonLat object" );
-    }
-    
-    function test_Layer_Google_overlay(t) {
-        // Test for #849.
-        t.plan(1);
-        var map = new OpenLayers.Map( 'map' , 
-        { controls: [] , 'numZoomLevels':20});
-    
-        var satellite = new OpenLayers.Layer.Google( "Google Satellite" , {type: google.maps.MapTypeId.SATELLITE, 'maxZoomLevel':18} );
-        var layer = new OpenLayers.Layer.WMS.Untiled( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic', 'transparent':true}, 
-                  {isBaseLayer: false} );
-    
-        map.addLayers([satellite, layer]);
-        map.setCenter(new OpenLayers.LonLat(10.205188,48.857593), 5);
-        map.zoomIn();
-        var size = map.getSize();
-        var px = new OpenLayers.Pixel(size.w, size.h);
-        var br = map.getLonLatFromPixel(px);
-        t.ok(layer.grid[0][0].bounds.containsLonLat(br), "Bottom right pixel is covered by untiled WMS layer");
-    }    
-    function test_Layer_Google_isBaseLayer (t) {
-        t.plan(3);
-        var map = new OpenLayers.Map( 'map' , 
-        { controls: [] , 'numZoomLevels':20});
-    
-        var satellite = new OpenLayers.Layer.Google( "Google Satellite" , {type: google.maps.MapTypeId.SATELLITE, 'maxZoomLevel':18} );
-        map.addLayers([satellite]);
-        map.zoomToMaxExtent();
-        
-        t.eq(satellite.div.style.display, "", "Satellite layer is visible.");
-        satellite.setVisibility(false);
-        t.eq(satellite.div.style.display, "none", "Satellite layer is not visible.");
-        satellite.setVisibility(true);
-        t.eq(satellite.div.style.display, "block", "Satellite layer is visible.");
-    }    
-    
-    function test_Layer_Google_setGMapVisibility(t) {
-        t.plan(3);
-    
-        var map = new OpenLayers.Map('map');
-        var gmap = new OpenLayers.Layer.Google("Google Streets");
-        var dummy = new OpenLayers.Layer("Dummy", {isBaseLayer: true});
-        map.addLayers([dummy, gmap]);
-        map.zoomToMaxExtent();
-    
-        // In v3, the terms of use and powered by elements are not available 
-        // until the layer loads.  This can occur before the layer is visible,
-        // but we don't try to access these elements until after the layer is
-        // made visible for the first time.  
-        var cache = OpenLayers.Layer.Google.cache[map.id];
-        t.ok(!cache.termsOfUse, "termsOfUse is not yet cached");
-        t.ok(!cache.poweredBy, "poweredBy is not yet cached");
-
-        var called = 0;
-        var original = gmap.repositionMapElements;
-        gmap.repositionMapElements = function() {
-            ++called;
-            original.apply(gmap, arguments);
-        }
-
-        map.setBaseLayer(gmap);
-        t.delay_call(4, function() {
-            t.ok(called > 0, "repositionMapElements called");
-            map.destroy();
-        });            
-    }
-
-    function test_Layer_Google_setGMapVisibility_allOverlays(t) {
-         t.plan(3);
-     
-         var map = new OpenLayers.Map('map', {allOverlays: true});
-         var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
-         var dummy = new OpenLayers.Layer("Dummy");
-         map.addLayers([gmap, dummy]);
-         map.zoomToMaxExtent();
-         
-         // In v3, the terms of use and powered by elements are not available 
-         // until the layer loads.  This can occur before the layer is visible,
-         // but we don't try to access these elements until after the layer is
-         // made visible for the first time.
-         var cache = OpenLayers.Layer.Google.cache[map.id];
-         t.ok(!cache.termsOfUse, "termsOfUse is not yet cached");
-         t.ok(!cache.poweredBy, "poweredBy is not yet cached");
-     
-         var called = 0;
-         var original = gmap.repositionMapElements;
-         gmap.repositionMapElements = function() {
-             ++called;
-             original.apply(gmap, arguments);
-         }    
-
-         gmap.setVisibility(true);
-         t.delay_call(2, function() {
-             t.ok(called > 0, "repositionMapElements called");
-             map.destroy();
-         });            
-     }
-
-     function test_allOverlays_invisible(t) {
-
-         t.plan(1);
-
-         var map = new OpenLayers.Map('map', {allOverlays: true});
-
-         var osm = new OpenLayers.Layer.OSM();
-         var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
-
-         // keep track of last argument to setGMapVisibility
-         var visible;
-         var original = gmap.setGMapVisibility;
-         gmap.setGMapVisibility = function(vis) {
-             visible = vis;
-             original.apply(gmap, arguments);
-         }
-
-         map.addLayers([osm, gmap]);
-         map.zoomToMaxExtent();
-
-         t.ok(visible === false, "setGMapVisibility last called with false");
-
-         map.destroy();
-
-     }
-     
-     function test_allOverlays_pan(t) {
-
-         t.plan(8);
-
-         var map = new OpenLayers.Map('map', {allOverlays: true});
-
-         var gmap = new OpenLayers.Layer.Google("Google Streets");
-         var osm = new OpenLayers.Layer.OSM();
-         map.addLayers([gmap, osm]);
-
-         var origin = new OpenLayers.LonLat(1000000, 6000000);
-         map.setCenter(origin, 4);
-         var resolution = map.getResolution();
-         
-         var dx, dy, center, expectedX, expectedY;
-
-         // confirm that panning works with Google visible
-         dx = 100, dy = -100;
-         map.pan(dx, dy, {animate: false});
-         center = map.getCenter();
-         expectedX = origin.lon + (resolution * dx);
-         expectedY = origin.lat - (resolution * dy);
-         t.eq(center.lon, expectedX, "x panning with Google visible " + dx + ", " + dy);
-         t.eq(center.lat, expectedY, "y panning with Google visible " + dx + ", " + dy);
-         map.pan(-dx, -dy, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, origin.lon, "x panning with Google visible " + (-dx) + ", " + (-dy));
-         t.eq(center.lat, origin.lat, "y panning with Google visible " + (-dx) + ", " + (-dy));
-
-         // confirm that panning works with Google invisible
-         gmap.setVisibility(false);
-         dx = 100, dy = -100;
-         map.pan(dx, dy, {animate: false});
-         center = map.getCenter();
-         expectedX = origin.lon + (resolution * dx);
-         expectedY = origin.lat - (resolution * dy);
-         t.eq(center.lon, expectedX, "x panning with Google invisible " + dx + ", " + dy);
-         t.eq(center.lat, expectedY, "y panning with Google invisible " + dx + ", " + dy);
-         map.pan(-dx, -dy, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, origin.lon, "x panning with Google invisible " + (-dx) + ", " + (-dy));
-         t.eq(center.lat, origin.lat, "y panning with Google invisible " + (-dx) + ", " + (-dy));
-         
-         map.destroy();
-
-     }
-     
-     function test_wrapDateLine(t) {
-         t.plan(2);
-
-         var map = new OpenLayers.Map("map");
-
-         var gmap = new OpenLayers.Layer.Google("Google Streets");
-         map.addLayer(gmap);
-         map.setCenter(new OpenLayers.LonLat(0, 0), 1);
-         
-         var center;
-         
-         // pan to the edge of the world
-         map.pan(256, 0, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, 20037508.3392, "edge of the world");
-         // pan off the edge of the world
-         map.pan(100, 0, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, -12210356.6442, "magically back in the western hemisphere");
-         
-         map.destroy();
-         
-     }
-
-     function test_respectDateLine(t) {
-         t.plan(2);
-
-         var map = new OpenLayers.Map("map");
-
-         var gmap = new OpenLayers.Layer.Google("Google Streets", {wrapDateLine: false});
-         map.addLayer(gmap);
-         map.setCenter(new OpenLayers.LonLat(0, 0), 1);
-         
-         var center;
-         
-         // pan to the edge of the world
-         map.pan(256, 0, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, 20037508.3392, "edge of the world");
-         // pan off the edge of the world
-         map.pan(100, 0, {animate: false});
-         center = map.getCenter();
-         t.eq(center.lon, 20037508.3392, "whew, still on the edge");
-         
-         map.destroy();
-         
-     }
-
-  </script>
-</head>
-<body>
-    <div id="map" style="width:500px; height: 500px"></div>
-</body>
-</html>
\ No newline at end of file

Copied: sandbox/ahocevar/playground/tests/Layer/Google/v3.html (from rev 10919, trunk/openlayers/tests/Layer/Google/v3.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Google/v3.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Layer/Google/v3.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,364 @@
+<html>
+<head>
+    <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+    var layer; 
+                   
+    function test_Layer_Google_constructor (t) {
+        t.plan( 5 );
+        
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.Google('Goog Layer');
+        map.addLayer(layer);
+        
+        
+        t.ok( layer instanceof OpenLayers.Layer.Google, "new OpenLayers.Layer.Google returns object" );
+        t.eq( layer.CLASS_NAME, "OpenLayers.Layer.Google", "CLASS_NAME variable set correctly");
+    
+        t.eq( layer.name, "Goog Layer", "layer.name is correct" );
+    
+        t.ok ( layer.mapObject != null, "GMap Object correctly loaded");
+        
+        t.eq(layer.version, "3", "API version 3 detected.");
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        var layer, clone;
+        
+        // test default layer
+        layer = new OpenLayers.Layer.Google();
+        clone = layer.clone();
+        t.ok(clone instanceof OpenLayers.Layer.Google, "[default] good instance");
+        
+        layer.destroy();
+        clone.destroy();
+        
+        // test with alt type
+        layer = new OpenLayers.Layer.Google(null, {type: google.maps.MapTypeId.SATELLITE});
+        clone = layer.clone();
+        t.ok(clone.type === google.maps.MapTypeId.SATELLITE, "[sat] correct type");
+        
+        layer.destroy();
+        clone.destroy();   
+    }
+    
+    function test_Layer_Google_isBaseLayer (t) {
+        t.plan(1);
+        
+        var layer = new OpenLayers.Layer.Google('Goog Layer');
+    
+        t.ok(layer.isBaseLayer, "a default load of google layer responds as a base layer");
+    }    
+    
+    function test_Layer_Google_Translation_lonlat (t) {
+        t.plan( 4 );
+        
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.Google('Goog Layer');
+        map.addLayer(layer);
+    
+    // these two lines specify an appropriate translation. 
+    //  the code afterwards works by itself to test that translation
+    //  works correctly both ways.
+       var gLatLng = new google.maps.LatLng(50,100);
+       // v3 uses sphericalMercator by default
+       var correspondingOLLonLat = new OpenLayers.LonLat(100,50).transform(
+           new OpenLayers.Projection("EPSG:4326"),
+           map.getProjectionObject()
+       );
+    
+    
+       olLonLat = layer.getOLLonLatFromMapObjectLonLat(gLatLng);
+       t.ok(olLonLat.equals(correspondingOLLonLat), "Translation from GLatLng to OpenLayers.LonLat works");
+    
+       var transGLatLng = layer.getMapObjectLonLatFromOLLonLat(olLonLat);
+       t.ok( transGLatLng.equals(gLatLng), "Translation from OpenLayers.LonLat to GLatLng works");
+    
+       t.ok( layer.getMapObjectLonLatFromOLLonLat(null) == null, "getGLatLngFromOLLonLat(null) returns null");
+       t.ok( layer.getOLLonLatFromMapObjectLonLat(null) == null, "getOLLonLatFromGLatLng(null) returns null");
+    }
+    
+    function test_Layer_Google_Translation_pixel (t) {
+        t.plan( 4 );
+        
+        var map = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.Google('Goog Layer');
+        map.addLayer(layer);
+    
+     // these two lines specify an appropriate translation. 
+     //  the code afterwards works by itself to test that translation
+     //  works correctly both ways.
+        var gPoint = new google.maps.Point(50,100);
+        var correspondingOLPixel = new OpenLayers.Pixel(50, 100);
+    
+    
+        olPixel = layer.getOLPixelFromMapObjectPixel(gPoint);
+        t.ok( olPixel.equals(correspondingOLPixel), "Translation from GPoint to OpenLayers.Pixel works");
+    
+        var transGPoint = layer.getMapObjectPixelFromOLPixel(olPixel);
+        t.ok( transGPoint.equals(gPoint), "Translation from OpenLayers.Pixel to GPoint works");
+    
+        t.ok( layer.getMapObjectPixelFromOLPixel(null) == null, "getGPointFromOLPixel(null) returns null");
+        t.ok( layer.getOLPixelFromMapObjectPixel(null) == null, "getOLPixelFromGPoint(null) returns null");
+    }
+    
+    function test_Layer_destroy (t) {
+        t.plan( 5 );    
+    
+        var map = new OpenLayers.Map('map');
+        
+        layer = new OpenLayers.Layer.Google('Test Layer');
+        map.addLayer(layer);
+    
+        layer.destroy();
+    
+        t.eq( layer.name, null, "layer.name is null after destroy" );
+        t.eq( layer.div, null, "layer.div is null after destroy" );
+        t.eq( layer.map, null, "layer.map is null after destroy" );
+        t.eq( layer.options, null, "layer.options is null after destroy" );
+        t.eq( layer.gmap, null, "layer.gmap is null after destroy" );
+    }
+    
+    function test_Layer_Goole_forwardMercator(t){
+        t.plan(2);
+        //Just test that the fowardMercator function still exists.
+        var layer = new OpenLayers.Layer.Google('Test Layer', {'sphericalMercator': true});
+        layer.forwardMercator = function(evt) {
+            t.ok(true,
+                 "GoogleMercator.forwardMercator was called and executed." );
+            return;
+        }
+        layer.forwardMercator();
+        //Now test the fowardMercator returns the expected LonLat object
+        var layer = new OpenLayers.Layer.Google('Test Layer', {'sphericalMercator': true});
+        var lonlat2 = new OpenLayers.LonLat(Math.random(),Math.random());
+        var result = layer.forwardMercator(lonlat2.lon, lonlat2.lat);
+        t.ok(result instanceof OpenLayers.LonLat, "OpenLayers.Google.fowardMercator returns LonLat object" );
+    }
+    
+    function test_Layer_Google_overlay(t) {
+        // Test for #849.
+        t.plan(1);
+        var map = new OpenLayers.Map( 'map' , 
+        { controls: [] , 'numZoomLevels':20});
+    
+        var satellite = new OpenLayers.Layer.Google( "Google Satellite" , {type: google.maps.MapTypeId.SATELLITE, 'maxZoomLevel':18} );
+        var layer = new OpenLayers.Layer.WMS.Untiled( "OpenLayers WMS", 
+                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic', 'transparent':true}, 
+                  {isBaseLayer: false} );
+    
+        map.addLayers([satellite, layer]);
+        map.setCenter(new OpenLayers.LonLat(10.205188,48.857593), 5);
+        map.zoomIn();
+        var size = map.getSize();
+        var px = new OpenLayers.Pixel(size.w, size.h);
+        var br = map.getLonLatFromPixel(px);
+        t.ok(layer.grid[0][0].bounds.containsLonLat(br), "Bottom right pixel is covered by untiled WMS layer");
+    }    
+    function test_Layer_Google_isBaseLayer (t) {
+        t.plan(3);
+        var map = new OpenLayers.Map( 'map' , 
+        { controls: [] , 'numZoomLevels':20});
+    
+        var satellite = new OpenLayers.Layer.Google( "Google Satellite" , {type: google.maps.MapTypeId.SATELLITE, 'maxZoomLevel':18} );
+        map.addLayers([satellite]);
+        map.zoomToMaxExtent();
+        
+        t.eq(satellite.div.style.display, "", "Satellite layer is visible.");
+        satellite.setVisibility(false);
+        t.eq(satellite.div.style.display, "none", "Satellite layer is not visible.");
+        satellite.setVisibility(true);
+        t.eq(satellite.div.style.display, "block", "Satellite layer is visible.");
+    }    
+    
+    function test_Layer_Google_setGMapVisibility(t) {
+        t.plan(3);
+    
+        var map = new OpenLayers.Map('map');
+        var gmap = new OpenLayers.Layer.Google("Google Streets");
+        var dummy = new OpenLayers.Layer("Dummy", {isBaseLayer: true});
+        map.addLayers([dummy, gmap]);
+        map.zoomToMaxExtent();
+    
+        // In v3, the terms of use and powered by elements are not available 
+        // until the layer loads.  This can occur before the layer is visible,
+        // but we don't try to access these elements until after the layer is
+        // made visible for the first time.  
+        var cache = OpenLayers.Layer.Google.cache[map.id];
+        t.ok(!cache.termsOfUse, "termsOfUse is not yet cached");
+        t.ok(!cache.poweredBy, "poweredBy is not yet cached");
+
+        var called = 0;
+        var original = gmap.repositionMapElements;
+        gmap.repositionMapElements = function() {
+            ++called;
+            original.apply(gmap, arguments);
+        }
+
+        map.setBaseLayer(gmap);
+        t.delay_call(4, function() {
+            t.ok(called > 0, "repositionMapElements called");
+            map.destroy();
+        });            
+    }
+
+    function test_Layer_Google_setGMapVisibility_allOverlays(t) {
+         t.plan(3);
+     
+         var map = new OpenLayers.Map('map', {allOverlays: true});
+         var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
+         var dummy = new OpenLayers.Layer("Dummy");
+         map.addLayers([gmap, dummy]);
+         map.zoomToMaxExtent();
+         
+         // In v3, the terms of use and powered by elements are not available 
+         // until the layer loads.  This can occur before the layer is visible,
+         // but we don't try to access these elements until after the layer is
+         // made visible for the first time.
+         var cache = OpenLayers.Layer.Google.cache[map.id];
+         t.ok(!cache.termsOfUse, "termsOfUse is not yet cached");
+         t.ok(!cache.poweredBy, "poweredBy is not yet cached");
+     
+         var called = 0;
+         var original = gmap.repositionMapElements;
+         gmap.repositionMapElements = function() {
+             ++called;
+             original.apply(gmap, arguments);
+         }    
+
+         gmap.setVisibility(true);
+         t.delay_call(2, function() {
+             t.ok(called > 0, "repositionMapElements called");
+             map.destroy();
+         });            
+     }
+
+     function test_allOverlays_invisible(t) {
+
+         t.plan(1);
+
+         var map = new OpenLayers.Map('map', {allOverlays: true});
+
+         var osm = new OpenLayers.Layer.OSM();
+         var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
+
+         // keep track of last argument to setGMapVisibility
+         var visible;
+         var original = gmap.setGMapVisibility;
+         gmap.setGMapVisibility = function(vis) {
+             visible = vis;
+             original.apply(gmap, arguments);
+         }
+
+         map.addLayers([osm, gmap]);
+         map.zoomToMaxExtent();
+
+         t.ok(visible === false, "setGMapVisibility last called with false");
+
+         map.destroy();
+
+     }
+     
+     function test_allOverlays_pan(t) {
+
+         t.plan(8);
+
+         var map = new OpenLayers.Map('map', {allOverlays: true});
+
+         var gmap = new OpenLayers.Layer.Google("Google Streets");
+         var osm = new OpenLayers.Layer.OSM();
+         map.addLayers([gmap, osm]);
+
+         var origin = new OpenLayers.LonLat(1000000, 6000000);
+         map.setCenter(origin, 4);
+         var resolution = map.getResolution();
+         
+         var dx, dy, center, expectedX, expectedY;
+
+         // confirm that panning works with Google visible
+         dx = 100, dy = -100;
+         map.pan(dx, dy, {animate: false});
+         center = map.getCenter();
+         expectedX = origin.lon + (resolution * dx);
+         expectedY = origin.lat - (resolution * dy);
+         t.eq(center.lon, expectedX, "x panning with Google visible " + dx + ", " + dy);
+         t.eq(center.lat, expectedY, "y panning with Google visible " + dx + ", " + dy);
+         map.pan(-dx, -dy, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, origin.lon, "x panning with Google visible " + (-dx) + ", " + (-dy));
+         t.eq(center.lat, origin.lat, "y panning with Google visible " + (-dx) + ", " + (-dy));
+
+         // confirm that panning works with Google invisible
+         gmap.setVisibility(false);
+         dx = 100, dy = -100;
+         map.pan(dx, dy, {animate: false});
+         center = map.getCenter();
+         expectedX = origin.lon + (resolution * dx);
+         expectedY = origin.lat - (resolution * dy);
+         t.eq(center.lon, expectedX, "x panning with Google invisible " + dx + ", " + dy);
+         t.eq(center.lat, expectedY, "y panning with Google invisible " + dx + ", " + dy);
+         map.pan(-dx, -dy, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, origin.lon, "x panning with Google invisible " + (-dx) + ", " + (-dy));
+         t.eq(center.lat, origin.lat, "y panning with Google invisible " + (-dx) + ", " + (-dy));
+         
+         map.destroy();
+
+     }
+     
+     function test_wrapDateLine(t) {
+         t.plan(2);
+
+         var map = new OpenLayers.Map("map");
+
+         var gmap = new OpenLayers.Layer.Google("Google Streets");
+         map.addLayer(gmap);
+         map.setCenter(new OpenLayers.LonLat(0, 0), 1);
+         
+         var center;
+         
+         // pan to the edge of the world
+         map.pan(256, 0, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, 20037508.3392, "edge of the world");
+         // pan off the edge of the world
+         map.pan(100, 0, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, -12210356.6442, "magically back in the western hemisphere");
+         
+         map.destroy();
+         
+     }
+
+     function test_respectDateLine(t) {
+         t.plan(2);
+
+         var map = new OpenLayers.Map("map");
+
+         var gmap = new OpenLayers.Layer.Google("Google Streets", {wrapDateLine: false});
+         map.addLayer(gmap);
+         map.setCenter(new OpenLayers.LonLat(0, 0), 1);
+         
+         var center;
+         
+         // pan to the edge of the world
+         map.pan(256, 0, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, 20037508.3392, "edge of the world");
+         // pan off the edge of the world
+         map.pan(100, 0, {animate: false});
+         center = map.getCenter();
+         t.eq(center.lon, 20037508.3392, "whew, still on the edge");
+         
+         map.destroy();
+         
+     }
+
+  </script>
+</head>
+<body>
+    <div id="map" style="width:500px; height: 500px"></div>
+</body>
+</html>
\ No newline at end of file

Modified: sandbox/ahocevar/playground/tests/Layer/Google.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Google.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Google.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -39,6 +39,33 @@
                           window.location.host);
         }
     }
+    
+    function test_clone(t) {
+        if (validkey) {
+            t.plan(2);
+            var layer, clone;
+            
+            // test default layer
+            layer = new OpenLayers.Layer.Google();
+            clone = layer.clone();
+            t.ok(clone instanceof OpenLayers.Layer.Google, "[default] good instance");
+            
+            layer.destroy();
+            clone.destroy();
+            
+            // test with alt type
+            layer = new OpenLayers.Layer.Google(null, {type: G_SATELLITE_MAP});
+            clone = layer.clone();
+            t.ok(clone.type === G_SATELLITE_MAP, "[sat] correct type");
+            
+            layer.destroy();
+            clone.destroy();   
+        } else {
+            t.plan(0);
+            t.debug_print("Google tests can't be run from " +
+                          window.location.host);
+        }
+    }
 
     function test_Layer_Google_isBaseLayer (t) {
         if(validkey) {
@@ -85,35 +112,6 @@
         }
     }
 
-    function test_Layer_Google_setMapType (t) {
-        if (validkey) {
-            t.plan(3);
-            var layer = new OpenLayers.Layer.Google('Goog Layer');
-            layer.map = {'events':{'unregister': function() {}}};
-            layer.loadMapObject();
-            layer.mapObject.getCenter= function()  { return true; }
-            layer.mapObject.getMapTypes = function() { return [0, 1]; }
-            layer.mapObject.addMapType = function(type) {
-                t.eq(type, 5, "new map type passed correctly.");
-            }
-            layer.mapObject.setMapType = function(arg) { 
-               t.eq(arg, 5, "got map type"); 
-            }
-            layer.type = 5;
-            layer.setMapType();
-            layer.mapObject.setMapType = function(arg) { 
-               t.eq(arg, 0, "got map type"); 
-            }
-            layer.type = 0
-            layer.setMapType();
-            
-        } else {
-            t.plan(0);
-            t.debug_print("Google tests can't be run from " +
-                          window.location.host);
-        }
-    }
-
     function test_Layer_Google_Translation_pixel (t) {
         if(validkey) {
             t.plan( 4 );
@@ -236,8 +234,124 @@
             t.debug_print("Google tests can't be run from " +
                           window.location.host);
         }
-    }    
+    }
+    
+    function test_setOpacity(t) {
+        
+        t.plan(6);
+        
+        var map = new OpenLayers.Map("map");
+        var gmap = new OpenLayers.Layer.Google(
+            "Google Streets", // the default
+            {numZoomLevels: 20}
+        );
+        var ghyb = new OpenLayers.Layer.Google(
+            "Google Hybrid",
+            {type: G_HYBRID_MAP, numZoomLevels: 20}
+        );
+        var gsat = new OpenLayers.Layer.Google(
+            "Google Satellite",
+            {type: G_SATELLITE_MAP, numZoomLevels: 22}
+        );
+        map.addLayers([gmap, ghyb, gsat]);
+        map.zoomToMaxExtent();
+        
+        var container = map.baseLayer.mapObject.getContainer();
+        var opacityCheck = function(opacity) {
+            var style = container.style;
+            var current = style.opacity === "" ? 1 : parseFloat(style.opacity);
+            if (style.filter && !style.opacity) {
+                current = Number(style.filter.replace(/alpha\(opacity=(.+?)\)/, "$1"));
+            }
+            return (current === opacity);
+        };
+        
+        gmap.setOpacity(0.5);
+        t.ok(opacityCheck(0.5), "container opacity set for visible layer");
+        
+        ghyb.setOpacity(0.75);
+        t.ok(opacityCheck(0.5), "container opacity not changed if layer not visible");
+        map.setBaseLayer(ghyb);
+        t.ok(opacityCheck(0.75), "container opacity changed to 0.75 when layer becomes visible");
+        
+        map.setBaseLayer(gsat);
+        t.ok(opacityCheck(1), "container opacity set to 1 by default");
+        gsat.setOpacity(0.25);
+        t.ok(opacityCheck(0.25), "container opacity changed to 0.25 for visible layer");
+        
+        map.setBaseLayer(gmap);
+        t.ok(opacityCheck(0.5), "container opacity set to layer opacity");
+        
+        map.destroy();
+        
+    }
 
+    function test_Layer_Google_setGMapVisibility(t) {
+        if(validkey) {
+            t.plan(4);
+
+            var map1 = new OpenLayers.Map('map');
+            var gmap1 = new OpenLayers.Layer.Google("Google Streets");
+            var dummy1 = new OpenLayers.Layer("Dummy", {isBaseLayer: true});
+            map1.addLayers([dummy1, gmap1]);
+            map1.zoomToMaxExtent();
+            
+            t.delay_call(2, function() {
+                t.ok(gmap1.termsOfUse.style.display == "none" || gmap1.termsOfUse.style.left == "-9999px", "termsOfUse is not visible");
+                t.eq(gmap1.poweredBy.style.display, "none", "poweredBy is not visible");
+                map1.destroy();
+            });            
+            
+            var map2 = new OpenLayers.Map('map', {allOverlays: true});
+            var gmap2 = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
+            var dummy2 = new OpenLayers.Layer("Dummy");
+            map2.addLayers([gmap2, dummy2]);
+            map2.zoomToMaxExtent();
+            
+            t.delay_call(2, function() {
+                t.ok(gmap2.termsOfUse.style.display == "none" || gmap2.termsOfUse.style.left == "-9999px", "allOverlays:true - termsOfUse is not visible");
+                t.eq(gmap2.poweredBy.style.display, "none", "allOverlays:true - poweredBy is not visible");
+                map2.destroy();
+            });            
+        } else {
+            t.plan(0);
+            t.debug_print("Google tests can't be run from " +
+                          window.location.host);
+        }    
+    }
+    
+    function test_sphericalMercator(t) {
+        
+        t.plan(4);
+        var map, layer;
+
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer.Google();
+        map.addLayer(layer);
+        t.ok(!layer.sphericalMercator, "sphericalMercator false by default");
+        t.eq(map.getProjection(), "EPSG:4326", "4326 by default without sphericalMercator");
+        map.destroy();
+        
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer.Google(null, {
+            sphericalMercator: true
+        });
+        map.addLayer(layer);
+        t.eq(map.getProjection(), "EPSG:900913", "900913 by default with sphericalMercator");
+        map.destroy();
+
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer.Google(null, {
+            sphericalMercator: true,
+            projection: "EPSG:102113"
+        });
+        map.addLayer(layer);
+        t.eq(map.getProjection(), "EPSG:102113", "custom code respected with sphericalMercator");
+        map.destroy();
+        
+    }
+    
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Layer/Grid.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Grid.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Grid.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -595,7 +595,7 @@
 
     function test_Layer_Grid_destroy (t) {
 
-        t.plan( 5 );
+        t.plan( 7 );
 
         var map = new OpenLayers.Map('map');
         layer = new OpenLayers.Layer.Grid(name, url, params);
@@ -620,6 +620,15 @@
         t.eq( tile.imgDiv, null, "Tile destroyed" ); 
         
         t.ok( layer.grid == null, "tiles appropriately destroyed")
+
+        // destroy after remove from map
+        layer = new OpenLayers.Layer.WMS(name, url, params);
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0,0), 10);
+        map.removeLayer(layer);
+        layer.destroy();
+        t.eq( layer.grid, null, "layer.grid is null after destroy" );
+        t.eq( layer.tileSize, null, "layer.tileSize is null after destroy" );
     }
     
 

Modified: sandbox/ahocevar/playground/tests/Layer/HTTPRequest.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/HTTPRequest.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/HTTPRequest.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -45,7 +45,7 @@
 
         // correct bubbling up to Layer.initialize()
         t.eq( layer.name, name, "layer.name is correct" );
-        t.ok( ((layer.options["chicken"] == 151) && (layer.options["foo"] == "bar")), "layer.options correctly set" );
+        t.eq( layer.options, options, "layer.options correctly set" );
 
         // HTTPRequest-specific properties
         t.eq( layer.url, url, "layer.name is correct" );
@@ -65,9 +65,19 @@
     }
 
     function test_Layer_HTTPRequest_mergeNewParams (t) {
-        t.plan( 4 );
+        t.plan( 8 );
 
+        var map = new OpenLayers.Map('map');
         layer = new OpenLayers.Layer.HTTPRequest(name, url, params, options);
+        map.addLayer(layer);
+
+        var scope = {some: "scope"}, log = [];
+        map.events.on({
+            changelayer: function(e) {
+                log.push({layer: e.layer, property: e.property, scope: this});
+            },
+            scope: scope
+        });
         
         var newParams = { layers: 'sooper', 
                           chickpeas: 'image/png'};
@@ -76,6 +86,10 @@
         
         t.eq( layer.params.layers, "sooper", "mergeNewParams() overwrites well");
         t.eq( layer.params.chickpeas, "image/png", "mergeNewParams() adds well");
+        t.eq( log.length, 1, "mergeNewParams() triggers changelayer once");
+        t.ok( log[0].layer == layer, "mergeNewParams() passes changelayer listener the expected layer");
+        t.ok( log[0].property == "params", "mergeNewParams() passes changelayer listener the property \"params\"");
+        t.eq( log[0].scope, scope, "mergeNewParams() executes changelayer listener with expected scope");
 
         newParams.chickpeas = 151;
 
@@ -85,8 +99,6 @@
             t.ok(true, "layer.mergeNewParams calls layer.redraw");
         }
         layer.mergeNewParams();
-
-
     }
 
     function test_Layer_HTTPRequest_getFullRequestString (t) {

Modified: sandbox/ahocevar/playground/tests/Layer/Image.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Image.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Image.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -7,7 +7,7 @@
     function test_Layer_Image_constructor (t) {
         t.plan( 13 );
         
-        var options = { chicken: 151, foo: "bar", projection: "none" };
+        var options = { chicken: 151, foo: "bar", projection: "EPSG:4326" };
         var layer = new OpenLayers.Layer.Image('Test Layer',
                                         'http://earthtrends.wri.org/images/maps/4_m_citylights_lg.gif',
                                                                         new OpenLayers.Bounds(-180, -88.759, 180, 88.759),
@@ -18,7 +18,7 @@
 
         t.eq( layer.name, "Test Layer", "layer.name is correct" );
         t.ok( layer.id != null, "Layer is given an id");
-        t.eq( layer.projection, "none", "default layer projection correctly set");
+        t.eq( layer.projection.getCode(), "EPSG:4326", "default layer projection correctly set");
         t.ok( ((layer.chicken == 151) && (layer.foo == "bar")), "layer.options correctly set to Layer Object" );
         t.ok( ((layer.options["chicken"] == 151) && (layer.options["foo"] == "bar")), "layer.options correctly backed up" );
 

Modified: sandbox/ahocevar/playground/tests/Layer/MapServer.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/MapServer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/MapServer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -226,7 +226,7 @@
                        (window.location.host == "localhost") ||
                        (window.location.host == "openlayers.org");
         
-        if (OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") {
+        if (OpenLayers.BROWSER_NAME == "opera" || OpenLayers.BROWSER_NAME == "safari") {
             t.plan(1);
             t.debug_print("Can't test google reprojection in Opera or Safari.");
         } else if(validkey) {

Modified: sandbox/ahocevar/playground/tests/Layer/MultiMap.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/MultiMap.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/MultiMap.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,40 +1,54 @@
 <html>
 <head>
-      <script type="text/javascript" src="http://clients.multimap.com/API/maps/1.1/metacarta_04"></script>
+  <!-- multimap api key for http://(www.)openlayers.org -->
+  <script type="text/javascript" src="http://developer.multimap.com/API/maps/1.2/OA10072915821139765"></script>
   <script src="../../lib/OpenLayers.js"></script>
   <script type="text/javascript">
-    var layer; 
+    var doTest = true;
+    function test_Layer_MultiMap_constructor (t) {
+        // WebKit browsers fail when the API key is for a different url, so we
+        // do not test in this case.
+        try {
+            var map = new OpenLayers.Map("map");
+            var layer = new OpenLayers.Layer.MultiMap('MultiMap Layer');
+            map.addLayer(layer);
+        }
+        catch(e) {
+            doTest = false;
+        }
 
-    function test_Layer_MultiMap_constructor (t) {
+        if (!doTest) { t.plan(0); return; }
         t.plan( 4 );
         
         var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.MultiMap('Goog Layer');
+        var layer = new OpenLayers.Layer.MultiMap('MultiMap Layer');
         map.addLayer(layer);
         
         
         t.ok( layer instanceof OpenLayers.Layer.MultiMap, "new OpenLayers.Layer.MultiMap returns object" );
         t.eq( layer.CLASS_NAME, "OpenLayers.Layer.MultiMap", "CLASS_NAME variable set correctly");
 
-        t.eq( layer.name, "Goog Layer", "layer.name is correct" );
+        t.eq( layer.name, "MultiMap Layer", "layer.name is correct" );
 
         t.ok ( layer.mapObject != null, "MultiMap Object correctly loaded");
     }
 
     function test_Layer_MultiMap_isBaseLayer (t) {
+        if (!doTest) { t.plan(0); return; }
         t.plan(1);
         
-        var layer = new OpenLayers.Layer.MultiMap('Goog Layer');
+        var layer = new OpenLayers.Layer.MultiMap('MultiMap Layer');
 
-        t.ok(layer.isBaseLayer, "a default load of google layer responds as a base layer");
+        t.ok(layer.isBaseLayer, "a default load of multimap layer responds as a base layer");
     }    
 
     function test_Layer_MultiMap_Translation_lonlat (t) {
+        if (!doTest) { t.plan(0); return; }
         
         t.plan( 4 );
         
         var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.MultiMap('Goog Layer');
+        var layer = new OpenLayers.Layer.MultiMap('MultiMap Layer');
         map.addLayer(layer);
 
      // these two lines specify an appropriate translation. 
@@ -55,11 +69,12 @@
     }
 
     function test_Layer_MultiMap_Translation_pixel (t) {
+        if (!doTest) { t.plan(0); return; }
         
         t.plan( 4 );
         
         var map = new OpenLayers.Map('map');
-        var layer = new OpenLayers.Layer.MultiMap('Goog Layer');
+        var layer = new OpenLayers.Layer.MultiMap('MultiMap Layer');
         map.addLayer(layer);
 
      // these two lines specify an appropriate translation. 
@@ -81,6 +96,7 @@
 
 
     function test_Layer_destroy (t) {
+        if (!doTest) { t.plan(0); return; }
         t.plan( 5 );    
 
         var map = new OpenLayers.Map('map');

Modified: sandbox/ahocevar/playground/tests/Layer/SphericalMercator.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/SphericalMercator.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/SphericalMercator.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -69,7 +69,7 @@
          
         t.eq(strToFixed(point.toString()), 
              strToFixed("POINT(10.000000828446318 20.000000618997227)"), 
-             "point transforms from EPSG:4326 to Spherical Mercator"); 
+             "point transforms from Spherical Mercator to EPSG:4326"); 
     }
     
     function test_SphericalMercator_addTransform(t) {
@@ -88,6 +88,48 @@
              "from EPSG:900913 to EPSG:4326 correctly defined");
     }
     
+    function test_equivalence(t) {
+
+        // list of equivalent codes for web mercator
+        var codes = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"];
+        var len = codes.length;
+        
+        t.plan(len + (len * len));
+
+        var ggPoint = new OpenLayers.Geometry.Point(10, 20);
+        var smPoint = new OpenLayers.Geometry.Point(1113195, 2273031);
+        
+        var gg = new OpenLayers.Projection("EPSG:4326");
+        
+        var i, proj, forward, inverse, other, j, equiv;
+        for (i=0, len=codes.length; i<len; ++i) {
+            proj = new OpenLayers.Projection(codes[i]);
+            
+            // confirm that forward/inverse work
+            forward = ggPoint.clone().transform(gg, proj);
+            t.eq(
+                strToFixed(forward.toString()), 
+                strToFixed("POINT(1113194.9077777779 2273030.9266712805)"), 
+                "transforms from EPSG:4326 to " + proj
+            );
+            inverse = smPoint.clone().transform(proj, gg);
+            t.eq(
+                strToFixed(inverse.toString()), 
+                strToFixed("POINT(10.000000828446318 20.000000618997227)"), 
+                "transforms from " + proj + " to EPSG:4326"
+            ); 
+            
+            // confirm that null transform works
+            for (j=i+1; j<len; ++j) {
+                other = new OpenLayers.Projection(codes[j]);
+                equiv = ggPoint.clone().transform(proj, other);
+                t.ok(proj.equals(other),  proj + " and " + other + " are equivalent");
+                t.ok(ggPoint.equals(equiv), "transform from " + proj + " to " + other + " preserves geometry");                
+            }
+        }
+
+    }
+    
   </script> 
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Layer/TMS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/TMS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/TMS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -166,6 +166,59 @@
         map.destroy();
     }
 
+    function test_zoomOffset(t) {
+
+        t.plan(2);
+        
+        var offset, zoom;
+        
+        // test offset of 2
+        offset = 2;
+        zoom = 3;
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            maxResolution: OpenLayers.Map.prototype.maxResolution / Math.pow(2, offset)
+        });
+        var layer = new OpenLayers.Layer.TMS("TMS", "", {
+            layername: "basic",
+            type: "png",
+            zoomOffset: offset
+        });
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0, 0), zoom);
+
+        var tileurl = layer.getURL(new OpenLayers.Bounds(3.515625,45,4.21875,45.703125));
+        level = parseInt(tileurl.split("/")[2]);
+        t.eq(parseInt(tileurl.split("/")[2]), zoom + offset, "correct level for offset 2");
+
+        map.destroy();
+
+        // test offset of -1
+        offset = -1;
+        zoom = 3;
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            maxResolution: OpenLayers.Map.prototype.maxResolution / Math.pow(2, offset)
+        });
+        var layer = new OpenLayers.Layer.TMS("TMS", "", {
+            layername: "basic",
+            type: "png",
+            zoomOffset: offset
+        });
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0, 0), zoom);
+
+        var tileurl = layer.getURL(new OpenLayers.Bounds(3.515625,45,4.21875,45.703125));
+        level = parseInt(tileurl.split("/")[2]);
+        t.eq(parseInt(tileurl.split("/")[2]), zoom + offset, "correct level for offset -1");
+
+        map.destroy();
+
+
+    }
+
     function test_Layer_TMS_setMap(t) {
 
         t.plan(3);

Modified: sandbox/ahocevar/playground/tests/Layer/Text.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Text.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Text.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -132,7 +132,7 @@
           layer.markers[1].events.triggerEvent('click', event);
           t.eq(map.popups.length, 1, "1st popup gone, 2nd Popup opened correctly");
           //Safari 3 separates style overflow into overflow-x and overflow-y
-          var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+          var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
           t.eq(map.popups[0].contentDiv.style[prop],"auto", "default Popup overflow correct");
         });
     }
@@ -151,12 +151,12 @@
           layer.markers[0].events.triggerEvent('click', event);
           t.eq(map.popups.length, 1, "Popup opened correctly");
           //Safari 3 separates style overflow into overflow-x and overflow-y
-          var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+          var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
           t.eq(map.popups[0].contentDiv.style[prop],"auto", "Popup overflow read from file");
           layer.markers[1].events.triggerEvent('click', event);
           t.eq(map.popups.length, 1, "1st popup gone, 2nd Popup opened correctly");
           //Safari 3 separates style overflow into overflow-x and overflow-y
-          var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+          var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
           t.eq(map.popups[0].contentDiv.style[prop],"hidden", "Popup overflow read from file");
         });
     }

Modified: sandbox/ahocevar/playground/tests/Layer/Vector.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/Vector.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/Vector.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -6,7 +6,7 @@
     var name = "Vector Layer";
     
     function test_Layer_Vector_constructor(t) {
-        t.plan(4);
+        t.plan(5);
 
         var options = {protocol: new OpenLayers.Protocol(), 
                        strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
@@ -19,8 +19,47 @@
         t.ok((layer.name == layer.strategies[0].layer.name) &&
              (layer.strategies[0].layer.name == layer.strategies[1].layer.name), 
              "setLayer was called on strategies");
+
+       options.renderers = [OpenLayers.Renderer.SVG, OpenLayers.Renderer.VML, OpenLayers.Renderer.Canvas]; 
+       layer.destroy(); 
+       layer = new OpenLayers.Layer.Vector(name, options); 
+       t.ok(layer.renderer.CLASS_NAME, "layer has a renderer when providing a function"); 
+       layer.destroy(); 
     }
 
+    function test_Layer_Vector_assignRenderer(t) { 
+        t.plan(2);
+ 
+        // create a dummy class in the global name space 
+        My = { 
+            Custom: { 
+                Renderer: { 
+                    Supported: OpenLayers.Class(OpenLayers.Renderer, { 
+                        supported: OpenLayers.Function.True, 
+                        CLASS_NAME: 'My.Custom.Renderer.Supported' 
+                    }), 
+                    NotSupported: OpenLayers.Class(OpenLayers.Renderer, { 
+                        supported: OpenLayers.Function.False, 
+                        CLASS_NAME: 'My.Custom.Renderer.NotSupported' 
+                    }) 
+                } 
+            } 
+        }; 
+        var layer = new OpenLayers.Layer.Vector('vector', { 
+            renderers: [My.Custom.Renderer.NotSupported, 
+                My.Custom.Renderer.Supported, 
+                OpenLayers.Renderer.Canvas] 
+        }); 
+        t.eq(layer.renderer.CLASS_NAME, 'My.Custom.Renderer.Supported',  
+            'layer has a valid renderer'); 
+ 
+        var layer = new OpenLayers.Layer.Vector('vector', { 
+            renderers: ['SVG', 'VML', 'Canvas', My.Custom.Renderer.Supported] 
+        }); 
+        t.ok(layer.renderer.CLASS_NAME != 'My.Custom.Renderer.Supported',  
+            'renderers can be strings as well'); 
+    }
+
     function test_Layer_Vector_refresh(t) {
         t.plan(4);
 
@@ -115,6 +154,47 @@
         t.eq(extent.toBBOX(), "-111.04,45.68,-111.04,45.68", "extent from getDataExtent is correct");
     }
 
+    function test_Layer_Vector_getFeature(t) {
+        t.plan(13);
+
+        var layer = new OpenLayers.Layer.Vector(name);
+        var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-111.04, 45.68));
+
+        t.ok(layer.getFeatureById(feature.id) == null,
+             "OpenLayers.Layer.Vector.getFeatureById returns null while the layer is empty");
+        t.ok(layer.getFeatureByFid('my_fid') == null,
+             "OpenLayers.Layer.Vector.getFeatureByFid returns null while the layer is empty");
+
+        layer.addFeatures([feature]);
+
+        t.ok(layer.getFeatureByFid('my_fid') == null,
+             "OpenLayers.Layer.Vector.getFeatureByFid returns null on unset feature fid");
+
+        feature.fid = 'my_fid';
+
+        t.ok(layer.getFeatureById(feature.id) == feature,
+             "OpenLayers.Layer.Vector.getFeatureById returns the correct feature");
+        t.ok(layer.getFeatureByFid(feature.fid) == feature,
+             "OpenLayers.Layer.Vector.getFeatureByFid returns the correct feature");
+        t.ok(layer.getFeatureById('some_id_that_does_not_exist') == null,
+             "OpenLayers.Layer.Vector.getFeatureById returns null on non-existing feature id");
+        t.ok(layer.getFeatureByFid('some_fid_that_does_not_exist') == null,
+             "OpenLayers.Layer.Vector.getFeatureByFid returns null on non-existing feature fid");
+        t.ok(layer.getFeatureById(feature.fid) == null,
+             "OpenLayers.Layer.Vector.getFeatureById ignores the feature fid");
+        t.ok(layer.getFeatureByFid(feature.id) == null,
+             "OpenLayers.Layer.Vector.getFeatureByFid ignores the feature id");
+
+        t.ok(layer.getFeatureBy('id', feature.id) == feature,
+             "OpenLayers.Layer.Vector.getFeatureBy('id', ...) works like getFeatureById on existing feature id");
+        t.ok(layer.getFeatureBy('id', 'some_id_that_does_not_exist') == null,
+             "OpenLayers.Layer.Vector.getFeatureBy('id', ...) works like getFeatureById on non-existing feature id");
+        t.ok(layer.getFeatureBy('fid', feature.fid) == feature,
+             "OpenLayers.Layer.Vector.getFeatureBy('fid', ...) works like getFeatureByFid on existing feature fid");
+        t.ok(layer.getFeatureBy('fid', 'some_fid_that_does_not_exist') == null,
+             "OpenLayers.Layer.Vector.getFeatureBy('fid', ...) works like getFeatureByFid on non-existing feature fid");
+    }
+
     function test_Layer_Vector_getDataExtent(t) {
         t.plan(1);
         var layer = new OpenLayers.Layer.Vector(name);
@@ -130,28 +210,72 @@
     }
 
     function test_Layer_Vector_removeFeatures(t) {
-        t.plan(9);
+        t.plan(17);
     
         var layer = new OpenLayers.Layer.Vector(name);
+        var features, log;
 
         var point1 = new OpenLayers.Geometry.Point(-111.04, 45.68);
-        var pointFeature1 = new OpenLayers.Feature.Vector(layer, point1);
+        var pointFeature1 = new OpenLayers.Feature.Vector(point1);
         var point2 = new OpenLayers.Geometry.Point(-111.14, 45.78);
-        var pointFeature2 = new OpenLayers.Feature.Vector(layer, point2);
-      
+        var pointFeature2 = new OpenLayers.Feature.Vector(point2);
+
+        // 1 test
         layer.addFeatures([pointFeature1, pointFeature2]);
-        var features = layer.removeFeatures([pointFeature1]);
-        
+        features = layer.removeFeatures([pointFeature1]);
         t.ok(layer.features.length == 1, "OpenLayers.Layer.Vector.removeFeatures removes a feature from the features array");
+
+        // 1 test
         layer.addFeatures([pointFeature1.clone(), pointFeature2.clone()]);
         layer.selectedFeatures.push(layer.features[0]); 
         layer.removeFeatures(layer.features[0]);
         t.eq(layer.selectedFeatures, [], "Remove features removes selected features");
-        var features = layer.removeFeatures(layer.features);
-        
+
+        // 1 test
+        features = layer.removeFeatures(layer.features);
         t.ok(layer.features.length == 0,
              "OpenLayers.Layer.Vector.removeFeatures(layer.features) removes all feature from the features array");
 
+        // 4 tests
+        log = [];
+        layer.addFeatures([pointFeature1, pointFeature2]);
+        layer.events.register("featuresremoved", null, function(obj) {
+            log.push(obj);
+        });
+        layer.removeFeatures(layer.features);
+        t.eq(log.length, 1,
+             "\"featuresremoved\" triggered once [0]");
+        t.eq(log[0].features.length, 2,
+             "\"featuresremoved\" listener is passed two features [0]");
+        t.ok(log[0].features[0] == pointFeature1,
+             "\"featuresremoved\" listener is passed the correct feature at index 0 [0]");
+        t.ok(log[0].features[1] == pointFeature2,
+             "\"featuresremoved\" listener is passed the correct feature at index 1 [0]");
+        layer.events.remove("featuresremoved");
+
+        // 4 tests
+        log = [];
+        layer.addFeatures([
+            pointFeature1, pointFeature2,
+            pointFeature1.clone(), pointFeature2.clone()
+        ]);
+        layer.selectedFeatures.push(pointFeature1);
+        layer.selectedFeatures.push(pointFeature2);
+        layer.events.register("featuresremoved", null, function(obj) {
+            log.push(obj);
+        });
+        layer.removeFeatures(layer.selectedFeatures);
+        t.eq(log.length, 1,
+             "\"featuresremoved\" triggered once [1]");
+        t.eq(log[0].features.length, 2,
+             "\"featuresremoved\" listener is passed two features [1]");
+        t.ok(log[0].features[0] == pointFeature1,
+             "\"featuresremoved\" listener is passed the correct feature at index 0 [1]");
+        t.ok(log[0].features[1] == pointFeature2,
+             "\"featuresremoved\" listener is passed the correct feature at index 1 [1]");
+        layer.events.remove("featuresremoved");
+        layer.removeFeatures(layer.features);
+
         // 6 tests
         layer.events.register('beforefeatureremoved', null, function(obj) {
             t.ok(pointFeature1 == obj.feature,
@@ -329,12 +453,12 @@
     }
 
     function test_Layer_Vector_destroyFeatures (t) {
-        t.plan(5); 
-        layer = new OpenLayers.Layer.Vector(name);
+        t.plan(8);
+        var layer = new OpenLayers.Layer.Vector(name);
         var map = new OpenLayers.Map('map');
         map.addLayer(layer);
-        var features = [];
-        for (var i = 0; i < 5; i++) {
+        var features = [], i;
+        for (i = 0; i < 5; i++) {
             features.push(new OpenLayers.Feature.Vector(
                           new OpenLayers.Geometry.Point(0,0)));
         }
@@ -344,8 +468,15 @@
         layer.destroyFeatures();
         t.eq(layer.features.length, 0, "destroyFeatures triggers removal");
         t.eq(layer.selectedFeatures, [], "Destroy features removes selected features");
+        var allDestroyed = true;
+        for (i = 0; i < 5; i++) {
+            if(features[i].geometry) {
+                allDestroyed = false;
+            }
+        }
+        t.ok(allDestroyed, "destroyFeatures actually destroys features");
         features = [];
-        for (var i = 0; i < 5; i++) {
+        for (i = 0; i < 5; i++) {
             features.push(new OpenLayers.Feature.Vector(
                           new OpenLayers.Geometry.Point(0,0)));
         }
@@ -355,6 +486,8 @@
         layer.destroyFeatures([features[0], features[1]]);
         t.eq(layer.features.length, 3, "destroyFeatures removes appropriate features");
         t.eq(layer.selectedFeatures, [], "destroyFeatures removes appropriate selected features");
+        t.eq(features[0].geometry, null, "destroyFeatures destroys feature 0");
+        t.eq(features[1].geometry, null, "destroyFeatures destroys feature 1");
     }
 
     function test_Layer_Vector_destroy (t) {
@@ -383,6 +516,18 @@
         }
         
     }
+    
+    function test_Layer_Vector_clone(t) {
+        t.plan(5);
+        var original = new OpenLayers.Layer.Vector(name, {dummyOption: "foo"});
+        original.addFeatures([new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2), {foo: "bar"})]);
+        var clone = original.clone();
+        t.ok(clone instanceof OpenLayers.Layer.Vector, "clone is an instance of OpenLayers.Layer.Vector");
+        t.ok(clone.name, original.name, "clone has the same name as the original");
+        t.ok(clone.features[0] != original.features[0], "clone's feature does not equal the original's feature");
+        t.eq(clone.features[0].attributes.foo, original.features[0].attributes.foo, "clone's feature has the same attributes as the original's feature");
+        t.eq(clone.dummyOption, original.dummyOption, "clone's dummyOption equals the original's dummy option");
+    }
 
     function test_Layer_Vector_externalGraphic(t) {
         t.plan(11);
@@ -465,7 +610,7 @@
                 feature.style = customStyle5;
                 layer.drawFeature(feature);
                 t.eq(root.firstChild.getAttributeNS(null, 'style'),
-                             'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
+                             'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.BROWSER_NAME == "opera" || OpenLayers.BROWSER_NAME == "safari") ? "" : ';'),
                              "graphicOpacity correctly set");
                 feature.style = customStyle6;
                 layer.drawFeature(feature);
@@ -512,6 +657,8 @@
                              "height is set correctly");
                 feature.style = customStyle4;
                 layer.drawFeature(feature);
+                var left = parseInt(root.firstChild.style.left);
+                var top = parseInt(root.firstChild.style.top);
                 t.eq(root.firstChild.style.height,
                              customStyle4.graphicHeight.toString()+'px',
                              "given graphicHeight and graphicWidth, both are set: height");
@@ -535,19 +682,102 @@
                              "graphicOpacity correctly set"); 
                 feature.style = customStyle6;
                 layer.drawFeature(feature);
-                var x = geometryX / renderer.getResolution();
-                var y = geometryY / renderer.getResolution();
-                t.eq(root.firstChild.style.left,
-                            (x + customStyle6.graphicXOffset).toFixed().toString()+'px',
-                            "graphicXOffset correctly set");
-                            
-                t.eq(root.firstChild.style.top,
-                            (y - (customStyle6.graphicYOffset+parseInt(root.firstChild.style.height))).toFixed().toString()+'px',
-                            "graphicYOffset correctly set");
+                var offsetLeft = parseInt(root.firstChild.style.left);
+                var offsetTop = parseInt(root.firstChild.style.top);
+                t.eq((offsetLeft-left)*2, customStyle6.graphicXOffset, "graphicXOffset correctly set");
+                t.eq((top-offsetTop)*2, customStyle6.graphicYOffset, "graphicYOffset correctly set");
 
         }
     }
 
+    function test_removeLayer_drawFeature(t) {
+        // test behaviour when features are redrawn while
+        // the layer has been removed from the map
+
+        t.plan(1);
+
+        // set up
+
+        var map, layer, feature;
+
+        map = new OpenLayers.Map("map");
+        map.addLayer(new OpenLayers.Layer("base", {isBaseLayer: true}));
+
+        layer = new OpenLayers.Layer.Vector("vector");
+        map.addLayer(layer);
+
+        map.zoomToMaxExtent();
+
+        feature = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(1.0, 1.0));
+        layer.addFeatures(feature);
+
+        // test
+
+        map.removeLayer(layer);
+        layer.drawFeature(feature);
+        layer.drawFeature(feature);
+        map.addLayer(layer);
+
+        var count = 0, node;
+        while(node = document.getElementById(feature.geometry.id)) {
+            node.parentNode.removeChild(node);
+            count++;
+        }
+
+        t.eq(count, 1, "one geometry added, one geometry removed");
+
+        // tear down
+
+        map.destroy();
+    }
+
+    function test_vectorBeforeFeatureAddedVeto(t) {
+        t.plan( 4 );
+
+        var map = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer.Vector("");
+        map.addLayer(layer);
+        var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry(1.0, 1.0));
+        layer.addFeatures([feature]);
+
+        var addedFeatures = [];
+        var beforefeatureadded_veto = function(evt) { return false; };
+        layer.events.register("beforefeatureadded", layer, beforefeatureadded_veto);
+        layer.events.register("featuresadded", layer, function(evt) {
+            if (evt.features) {
+                for (var i = 0; i < evt.features.length; i++) {
+                    addedFeatures.push(evt.features[i]);
+                }
+            }
+        });
+
+        var blankFeatures = [
+            new OpenLayers.Feature.Vector(new OpenLayers.Geometry(1.0, 1.0)),
+            new OpenLayers.Feature.Vector(new OpenLayers.Geometry(1.0, 1.0))];
+        layer.addFeatures(blankFeatures);
+
+        t.eq(layer.features.length, 1,
+            "features not added to layer after beforefeatureadded veto");
+        t.eq(addedFeatures.length, 0,
+            "no features sent to featuresadded on feature veto");
+
+        addedFeatures = [];
+
+        layer.events.unregister("beforefeatureadded", layer, beforefeatureadded_veto);
+        beforefeatureadded_veto = function(evt) { return true; };
+        layer.events.register("beforefeatureadded", layer, beforefeatureadded_veto);
+
+        layer.addFeatures(blankFeatures);
+
+        t.eq(layer.features.length, 3,
+            "features added to layer as expected");
+        t.eq(addedFeatures.length, 2,
+            "featuresadded event received expected number of features");
+    }
+
+
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Layer/WFS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/WFS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/WFS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -134,7 +134,7 @@
             map.setCenter(new OpenLayers.LonLat(-100, 60), 3);
         } catch (Exception) {
         }    
-        t.eq(layer.tile.url, "http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp?typename=OWLS&maxfeatures=10&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&SRS=EPSG%3A4326&BBOX=-187.890625,-36.6796875,-12.109375,156.6796875", "Tile URL is set correctly when not encoded");
+        t.eq(layer.tile.url, "http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp?TYPENAME=OWLS&MAXFEATURES=10&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&SRS=EPSG%3A4326&BBOX=-187.890625,-36.6796875,-12.109375,156.6796875", "Tile URL is set correctly when not encoded");
         map.destroy();     
         var map = new OpenLayers.Map('map');
         layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
@@ -152,7 +152,7 @@
             map.setCenter(new OpenLayers.LonLat(-100, 60), 3);
         } catch (Exception) {
         }  
-        t.eq(layer.tile.url, "http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp?typename=OWLS&maxfeatures=10&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&SRS=EPSG%3A4326&BBOX=-187.890625%2C-36.679687%2C-12.109375%2C156.679688", "Tile URL is set correctly when not encoded");
+        t.eq(layer.tile.url, "http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp?TYPENAME=OWLS&MAXFEATURES=10&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&SRS=EPSG%3A4326&BBOX=-187.890625%2C-36.679687%2C-12.109375%2C156.679688", "Tile URL is set correctly when not encoded");
         map.destroy();     
     }
     function test_projection_srs(t) {
@@ -160,7 +160,7 @@
         var map = new OpenLayers.Map('map');
         map.addLayer(new OpenLayers.Layer("",{isBaseLayer: true} ));
         // we use an empty moveTo function because we don't want to request tiles
-        var layer = new OpenLayers.Layer.WFS("","",{},{'projection': new OpenLayers.Projection("EPSG:900913"),
+        var layer = new OpenLayers.Layer.WFS("","/wfs",{},{'projection': new OpenLayers.Projection("EPSG:900913"),
             moveTo: function() {}});
         map.addLayer(layer);
         map.zoomToMaxExtent();

Deleted: sandbox/ahocevar/playground/tests/Layer/WMS/Post.html
===================================================================
--- trunk/openlayers/tests/Layer/WMS/Post.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/WMS/Post.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,87 +0,0 @@
-<html>
-<head>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
-    var isOpera   = (navigator.userAgent.indexOf("Opera") != -1);
-    var layer;
-
-    var name = 'Test Layer';
-    var url = "http://octo.metacarta.com/cgi-bin/mapserv";
-    var params = { map: '/mapdata/vmap_wms.map', 
-                   layers: 'basic', 
-                   format: 'image/jpeg'};
-
-    function test_Layer_WMS_Post_constructor (t) {
-        t.plan( 2 );
-
-        var url = "http://octo.metacarta.com/cgi-bin/mapserv";
-        var options = {unsupportedBrowsers: []};
-        layer = new OpenLayers.Layer.WMS.Post(name, url, params, options);
-
-        t.eq(
-            layer.usePost, true,
-            "Supported browsers use IFrame tiles.");
-
-        layer.destroy();
-
-        var options = { unsupportedBrowsers: [OpenLayers.BROWSER_NAME]};
-        layer = new OpenLayers.Layer.WMS.Post(name, url, params, options);
-        t.eq(
-            layer.usePost, false,
-            "unsupported browsers use Image tiles.");
-        layer.destroy();
-    }
-
-    function test_Layer_WMS_Post_addtile (t) {
-        t.plan( 3 );
-    
-        layer = new OpenLayers.Layer.WMS.Post(name, url, params);
-        var map = new OpenLayers.Map('map');
-        map.addLayer(layer);
-        var bounds = new OpenLayers.Bounds(1,2,3,4);
-        var pixel  = new OpenLayers.Pixel(5,6);
-        var tile   = layer.addTile(bounds, pixel);
-        
-        if(isMozilla || isOpera) {
-            t.ok(
-                tile instanceof OpenLayers.Tile.Image,
-                "tile is an instance of OpenLayers.Tile.Image");
-        }
-        else {
-            t.ok(
-                tile.useIFrame !== undefined,
-                "tile is created with the OpenLayers.Tile.Image.IFrame mixin");
-        }
-        map.destroy();
-
-        // test the unsupported browser
-        layer = new OpenLayers.Layer.WMS.Post(name, url, params, {
-            unsupportedBrowsers: [OpenLayers.BROWSER_NAME]
-        });
-        map   = new OpenLayers.Map('map');
-        map.addLayer(layer);
-        tile  = layer.addTile(bounds, pixel);
-        t.ok(
-            tile instanceof OpenLayers.Tile.Image,
-            "unsupported browser: tile is an instance of Tile.Image");
-        layer.destroy();
-
-        // test a supported browser
-        layer = new OpenLayers.Layer.WMS.Post(name, url, params, {
-            unsupportedBrowsers: []
-        });
-        map.addLayer(layer);
-        var tile2 = layer.addTile(bounds, pixel);
-        t.ok(
-            tile2.createIFrame,
-            "supported browser: tile is created with the Tile.Image.IFrame mixin");
-        map.destroy();
-    }
-
-  </script>
-</head>
-<body>
-<div id="map" style="width:500px;height:550px"></div>
-</body>
-</html>

Copied: sandbox/ahocevar/playground/tests/Layer/WMS/Post.html (from rev 10919, trunk/openlayers/tests/Layer/WMS/Post.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/WMS/Post.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Layer/WMS/Post.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,87 @@
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
+    var isOpera   = (navigator.userAgent.indexOf("Opera") != -1);
+    var layer;
+
+    var name = 'Test Layer';
+    var url = "http://octo.metacarta.com/cgi-bin/mapserv";
+    var params = { map: '/mapdata/vmap_wms.map', 
+                   layers: 'basic', 
+                   format: 'image/jpeg'};
+
+    function test_Layer_WMS_Post_constructor (t) {
+        t.plan( 2 );
+
+        var url = "http://octo.metacarta.com/cgi-bin/mapserv";
+        var options = {unsupportedBrowsers: []};
+        layer = new OpenLayers.Layer.WMS.Post(name, url, params, options);
+
+        t.eq(
+            layer.usePost, true,
+            "Supported browsers use IFrame tiles.");
+
+        layer.destroy();
+
+        var options = { unsupportedBrowsers: [OpenLayers.BROWSER_NAME]};
+        layer = new OpenLayers.Layer.WMS.Post(name, url, params, options);
+        t.eq(
+            layer.usePost, false,
+            "unsupported browsers use Image tiles.");
+        layer.destroy();
+    }
+
+    function test_Layer_WMS_Post_addtile (t) {
+        t.plan( 3 );
+    
+        layer = new OpenLayers.Layer.WMS.Post(name, url, params);
+        var map = new OpenLayers.Map('map');
+        map.addLayer(layer);
+        var bounds = new OpenLayers.Bounds(1,2,3,4);
+        var pixel  = new OpenLayers.Pixel(5,6);
+        var tile   = layer.addTile(bounds, pixel);
+        
+        if(isMozilla || isOpera) {
+            t.ok(
+                tile instanceof OpenLayers.Tile.Image,
+                "tile is an instance of OpenLayers.Tile.Image");
+        }
+        else {
+            t.ok(
+                tile.useIFrame !== undefined,
+                "tile is created with the OpenLayers.Tile.Image.IFrame mixin");
+        }
+        map.destroy();
+
+        // test the unsupported browser
+        layer = new OpenLayers.Layer.WMS.Post(name, url, params, {
+            unsupportedBrowsers: [OpenLayers.BROWSER_NAME]
+        });
+        map   = new OpenLayers.Map('map');
+        map.addLayer(layer);
+        tile  = layer.addTile(bounds, pixel);
+        t.ok(
+            tile instanceof OpenLayers.Tile.Image,
+            "unsupported browser: tile is an instance of Tile.Image");
+        layer.destroy();
+
+        // test a supported browser
+        layer = new OpenLayers.Layer.WMS.Post(name, url, params, {
+            unsupportedBrowsers: []
+        });
+        map.addLayer(layer);
+        var tile2 = layer.addTile(bounds, pixel);
+        t.ok(
+            tile2.createIFrame,
+            "supported browser: tile is created with the Tile.Image.IFrame mixin");
+        map.destroy();
+    }
+
+  </script>
+</head>
+<body>
+<div id="map" style="width:500px;height:550px"></div>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Layer/WMS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/WMS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/WMS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -6,20 +6,20 @@
 <script src="../../lib/OpenLayers.js"></script>
   <script type="text/javascript">
     var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
-    var layer; 
+    var layer;
 
     var name = 'Test Layer';
     var url = "http://octo.metacarta.com/cgi-bin/mapserv";
-    var params = { map: '/mapdata/vmap_wms.map', 
-                   layers: 'basic', 
+    var params = { map: '/mapdata/vmap_wms.map',
+                   layers: 'basic',
                    format: 'image/jpeg'};
 
     function test_Layer_WMS_constructor (t) {
         t.plan( 15 );
 
         var trans_format = "image/png";
-        if (OpenLayers.Util.alphaHack()) { trans_format = "image/gif"; } 
-        
+        if (OpenLayers.Util.alphaHack()) { trans_format = "image/gif"; }
+
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         layer = new OpenLayers.Layer.WMS(name, url, params);
         t.ok( layer instanceof OpenLayers.Layer.WMS, "new OpenLayers.Layer.WMS returns object" );
@@ -64,10 +64,10 @@
         params.TRANSPARENT = false;
 
     }
-    
+
     function test_Layer_WMS_addtile (t) {
         t.plan( 6 );
-    
+
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         layer = new OpenLayers.Layer.WMS(name, url, params);
         var map = new OpenLayers.Map('map');
@@ -103,10 +103,10 @@
         t.eq( tile.position.toString(), "x=5,y=6", "Position of tile is set correctly." );
         map.destroy();
     }
-    
+
     function test_Layer_WMS_bboxEncoding (t) {
         t.plan( 6 );
-    
+
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         layer = new OpenLayers.Layer.WMS(name, url, params, {encodeBBOX:true});
         var map = new OpenLayers.Map('map');
@@ -142,7 +142,7 @@
         t.eq( tile.position.toString(), "x=5,y=6", "Position of tile is set correctly." );
         map.destroy();
     }
-    
+
     function test_Layer_WMS_inittiles (t) {
         t.plan( 2 );
         var map = new OpenLayers.Map('map');
@@ -157,14 +157,14 @@
 
     function test_Layer_WMS_clone (t) {
         t.plan(4);
-        
+
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         var options = {tileSize: new OpenLayers.Size(500,50)};
         var map = new OpenLayers.Map('map', options);
         layer = new OpenLayers.Layer.WMS(name, url, params);
         map.addLayer(layer);
 
-        layer.grid = [ [6, 7], 
+        layer.grid = [ [6, 7],
                        [8, 9]];
 
         var clone = layer.clone();
@@ -185,7 +185,7 @@
 
     function test_Layer_WMS_isBaseLayer(t) {
         t.plan(3);
-        
+
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         layer = new OpenLayers.Layer.WMS(name, url, params);
         t.ok( layer.isBaseLayer, "baselayer is true by default");
@@ -205,8 +205,8 @@
         var map = new OpenLayers.Map("map");
         var url = "http://octo.metacarta.com/cgi-bin/mapserv";
         layer = new OpenLayers.Layer.WMS(name, url, params);
-        
-        var newParams = { layers: 'sooper', 
+
+        var newParams = { layers: 'sooper',
                           chickpeas: 'image/png'};
 
         map.addLayer(layer);
@@ -217,10 +217,10 @@
         }
 
         layer.mergeNewParams(newParams);
-        
+
         t.eq( layer.params.LAYERS, "sooper", "mergeNewParams() overwrites well");
         t.eq( layer.params.CHICKPEAS, "image/png", "mergeNewParams() adds well");
-    
+
         newParams.CHICKPEAS = 151;
 
         t.eq( layer.params.CHICKPEAS, "image/png", "mergeNewParams() makes clean copy of hashtable");
@@ -229,16 +229,16 @@
 
     function test_Layer_WMS_getFullRequestString (t) {
 
-        
-        t.plan( 2 );
+
+        t.plan( 3 );
         var map = new OpenLayers.Map('map');
         map.projection = "xx";
-        tUrl = "http://octo.metacarta.com/cgi-bin/mapserv";
-        tParams = { layers: 'basic', 
+        var tUrl = "http://octo.metacarta.com/cgi-bin/mapserv";
+        var tParams = { layers: 'basic',
                    format: 'image/png'};
         var tLayer = new OpenLayers.Layer.WMS(name, tUrl, tParams);
         map.addLayer(tLayer);
-        str = tLayer.getFullRequestString();
+        var str = tLayer.getFullRequestString();
         var tParams = {
             LAYERS: "basic", FORMAT: "image/png", SERVICE: "WMS",
             VERSION: "1.1.1", REQUEST: "GetMap", STYLES: "",
@@ -247,7 +247,7 @@
         t.eq(str,
              tUrl + "?" + OpenLayers.Util.getParameterString(tParams),
              "getFullRequestString() adds SRS value");
-        
+
         map.removeLayer(tLayer);
         tLayer.projection = "none";
         map.addLayer(tLayer);
@@ -257,7 +257,21 @@
              tUrl + "?" + OpenLayers.Util.getParameterString(tParams),
              "getFullRequestString() by default does *not* add SRS value if projection is 'none'");
         map.destroy();
- 
+        
+        map = new OpenLayers.Map("map", {projection: "EPSG:4326"});
+        var layerProj = new OpenLayers.Projection("FOO", {
+            equals: function() {return true},
+            getCode: function() {return "FOO"}
+        });
+        tLayer = new OpenLayers.Layer.WMS(name, tUrl, tParams, {projection: layerProj});
+        map.addLayer(tLayer);
+        str = tLayer.getFullRequestString();
+        tParams.SRS = "FOO";
+        t.eq(str,
+             tUrl + "?" + OpenLayers.Util.getParameterString(tParams),
+             "getFullRequestString() uses the layer projection if it equals the map projection");
+        map.destroy();
+
     }
 
     function test_Layer_WMS_setOpacity (t) {
@@ -266,9 +280,9 @@
         var map = new OpenLayers.Map('map');
         map.projection = "xx";
         tUrl = "http://octo.metacarta.com/cgi-bin/mapserv";
-        tParams = { layers: 'basic', 
+        tParams = { layers: 'basic',
                    format: 'image/png'};
-        tOptions = { 'opacity': '0.5' };           
+        tOptions = { 'opacity': '0.5' };
         var tLayer = new OpenLayers.Layer.WMS(name, tUrl, tParams, tOptions);
         map.addLayer(tLayer);
         map.zoomToMaxExtent();
@@ -283,13 +297,13 @@
         t.eq(parseFloat(tile.imgDiv.style.opacity), 0.6, "Tile opacity is set correctly");
 
         map.destroy();
-    }    
-    
+    }
+
     function test_Layer_WMS_Reproject (t) {
         var validkey = (window.location.protocol == "file:") ||
                        (window.location.host == "localhost") ||
                        (window.location.host == "openlayers.org");
-        if (OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") {
+        if (OpenLayers.BROWSER_NAME == "opera" || OpenLayers.BROWSER_NAME == "safari") {
             t.plan(1);
             t.debug_print("Can't test google reprojection in Opera or Safari.");
         } else if(validkey) {
@@ -304,17 +318,17 @@
             map.addLayer(wmslayer);
             map.setCenter(new OpenLayers.LonLat(0,0), 5);
             var tile = wmslayer.grid[0][0];
-            t.eq( tile.bounds.left, -22.5, "left side matches" ); 
-            t.eq( tile.bounds.right, -11.25, "right side matches" ); 
-            t.eq( tile.bounds.bottom.toFixed(6), '11.178402', "bottom side matches" ); 
-            t.eq( tile.bounds.top.toFixed(6), '21.943046', "top side matches" ); 
+            t.eq( tile.bounds.left, -22.5, "left side matches" );
+            t.eq( tile.bounds.right, -11.25, "right side matches" );
+            t.eq( tile.bounds.bottom.toFixed(6), '11.178402', "bottom side matches" );
+            t.eq( tile.bounds.top.toFixed(6), '21.943046', "top side matches" );
             map.destroy();
         } else {
             t.plan(1);
             t.debug_print("can't test google layer from " +
                           window.location.host);
         }
-        
+
         var map = new OpenLayers.Map('map');
         layer = new OpenLayers.Layer.WMS(name, url, params);
         map.addLayer(layer);
@@ -324,8 +338,8 @@
 
         map.destroy();
     }
-    
-    function test_Layer_WMS_noGutters (t) { 
+
+    function test_Layer_WMS_noGutters (t) {
         t.plan(2);
         var map = new OpenLayers.Map('map');
         var layer = new OpenLayers.Layer.WMS("no gutter layer", url, params, {gutter: 0});
@@ -340,12 +354,12 @@
         t.eq(parseInt(args['HEIGHT']),
              tile.size.h,
              "layer without gutter requests images that are as tall as the tile");
-        
+
         layer.destroy();
         map.destroy();
     }
 
-    function test_Layer_WMS_gutters (t) { 
+    function test_Layer_WMS_gutters (t) {
         t.plan(2);
         var gutter = 15;
         var map = new OpenLayers.Map('map');
@@ -368,16 +382,16 @@
     }
 
     // DEPRECATED -- REMOVE IN 3.0
-    function test_Layer_Untiled_WMS(t) { 
+    function test_Layer_Untiled_WMS(t) {
         t.plan(1);
-        
+
         var layer = new OpenLayers.Layer.WMS.Untiled();
-        
+
         var clone = layer.clone();
-        
+
         t.ok(clone.singleTile, "regression test: clone works. this is for #1013");
     }
-    
+
     function test_Layer_WMS_destroy (t) {
 
         t.plan( 1 );
@@ -389,16 +403,105 @@
         map.setCenter(new OpenLayers.LonLat(0,0), 5);
 
         //grab a reference to one of the tiles
-        var tile = layer.grid[0][0];        
+        var tile = layer.grid[0][0];
 
         layer.destroy();
-        
-    // checks to make sure superclass (grid) destroy() was called    
-        
+
+    // checks to make sure superclass (grid) destroy() was called
+
         t.ok( layer.grid == null, "grid set to null");
     }
-    
 
+    function test_Layer_WMS_v13(t) {
+
+        t.plan(6);
+
+        var lon = 5;
+        var lat = 40;
+        var zoom = 5;
+        var map = new OpenLayers.Map( 'map' );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://myserver.org/wms?",
+            {layers: 'mylayer', version: '1.3.0'},
+            {singleTile: true}
+        );
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var url = layer.getURL(map.getExtent());
+        var params = url.split("&");
+        var bbox;
+        for (var i=0, len=params.length; i<len; i++) {
+            var param = params[i];
+            var a = param.split('=');
+            if (a[0] === 'BBOX') {
+                bbox = a[1];
+                break;
+            }
+        }
+
+        t.eq(layer.params.CRS, "EPSG:4326", "In WMS 1.3 SRS is now CRS");
+        t.eq(bbox, "27.9150390625,-5.986328125,52.0849609375,15.986328125", "Axis sequence is lat lon for EPSG:4326 in WMS 1.3.0");
+
+        var layer2 = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://myserver.org/wms?",
+            {layers: 'mylayer', version: '1.1.1'},
+            {singleTile: true}
+        );
+        map.addLayer(layer2);
+
+        var url = layer2.getURL(map.getExtent());
+        var params = url.split("&");
+        var bbox;
+        for (var i=0, len=params.length; i<len; i++) {
+            var param = params[i];
+            var a = param.split('=');
+            if (a[0] === 'BBOX') {
+                bbox = a[1];
+                break;
+            }
+        }
+
+        t.eq(layer2.params.SRS, "EPSG:4326", "In WMS 1.1.1 parameter is called SRS");
+        t.eq(bbox, "-5.986328125,27.9150390625,15.986328125,52.0849609375", "Axis sequence is lon lat for EPSG:4326 in WMS 1.1.1");
+
+        map.destroy();
+
+        // CRS:84 has normal axis sequence (lon lat)
+        var map = new OpenLayers.Map( 'map', {projection: 'CRS:84'} );
+        var layer = new OpenLayers.Layer.WMS(
+            "OpenLayers WMS",
+            "http://myserver.org/wms?",
+            {layers: 'mylayer', version: '1.3.0'},
+            {singleTile: true}
+        );
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+
+        var url = layer.getURL(map.getExtent());
+        var params = url.split("&");
+        var bbox, exceptions;
+        for (var i=0, len=params.length; i<len; i++) {
+            var param = params[i];
+            var a = param.split('=');
+            if (a[0] === 'EXCEPTIONS') {
+                exceptions = a[1];
+            }
+            if (a[0] === 'BBOX') {
+                bbox = a[1];
+            }
+        }
+
+        t.eq(exceptions, "INIMAGE", "If not set, EXCEPTIONS should be INIMAGE for WMS 1.3");
+        t.eq(bbox, "-5.986328125,27.9150390625,15.986328125,52.0849609375", "Axis sequence for CRS:84 is lon lat");
+
+        map.destroy();
+
+    }
+
+
   </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Layer/WMTS.html (from rev 10919, trunk/openlayers/tests/Layer/WMTS.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/WMTS.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Layer/WMTS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,1424 @@
+<html>
+    <head>
+        <script src="../../lib/OpenLayers.js"></script>
+        <script type="text/javascript">    
+
+            function test_constructor(t) {
+                t.plan(6);        
+                var xml = document.getElementById("capabilities").firstChild.nodeValue;
+                var doc = new OpenLayers.Format.XML().read(xml);
+                var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+            
+                var layer0 = new OpenLayers.Layer.WMTS({
+                    name: "GeoWebCache USA WMTS", 
+                    url: "http://example.com/geowebcache-1.2.2/service/wmts/",
+                    layer: "arcgis-online-wms",
+                    style: "",
+                    matrixSet: "arcgis-online-wgs84",                
+                    format: "image/png",
+                    isBaseLayer: false,
+                    requestEncoding: "KVP",
+                    maxResolution: 0.3521969032857032,
+                    numZoomLevels: 7,
+                    matrixIds: obj.contents.tileMatrixSets["arcgis-online-wgs84"].matrixIds
+                });
+
+                t.ok(layer0 instanceof OpenLayers.Layer.WMTS, "constructor returns instance of OpenLayers.Layer.WMTS");
+                t.eq(layer0.formatSuffix, "png", "formatSuffix is set correct based on 'format' parameter");
+                
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });
+
+                t.ok(layer1 instanceof OpenLayers.Layer.WMTS, "constructor returns instance of OpenLayers.Layer.WMTS");
+                t.eq(layer1.formatSuffix, "jpg", "formatSuffix is set correct based on default format");
+                t.eq(layer1.tileSize.w, 512.0, "tileSize w is set correctly");
+                t.eq(layer1.tileSize.h, 512.0, "tileSize h is set correctly");
+            }
+
+            function test_moveTo(t) {
+                t.plan(9);        
+                var xml = document.getElementById("capabilities").firstChild.nodeValue;
+                var doc = new OpenLayers.Format.XML().read(xml);
+                var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+            
+                var layer0 = new OpenLayers.Layer.WMTS({
+                    name: "GeoWebCache USA WMTS", 
+                    url: "http://example.com/geowebcache-1.2.2/service/wmts/",
+                    layer: "arcgis-online-wms",
+                    style: "foo",
+                    matrixSet: "arcgis-online-wgs84",    
+                    format: "image/png",
+                    requestEncoding: "KVP",
+                    maxResolution: 0.3521969032857032,
+                    numZoomLevels: 7,
+                    matrixIds: obj.contents.tileMatrixSets["arcgis-online-wgs84"].matrixIds
+                });   
+
+                var map = new OpenLayers.Map('map');
+                map.addLayer(layer0);
+                
+                map.setCenter(new OpenLayers.LonLat(-97, 38), 1);
+                
+                t.ok((layer0.tileOrigin instanceof OpenLayers.LonLat), "tileOrigin is an instance of OpenLayers.LonLat");
+                t.ok((layer0.tileOrigin.lon == -180 && layer0.tileOrigin.lat == 90), "tileOrigin is set correctly");
+                t.ok((layer0.tileSize instanceof OpenLayers.Size), "tileSize is an instance of OpenLayers.Size");
+                t.eq(layer0.tileSize.w, 256.0, "tileSize w is set correctly");
+                t.eq(layer0.tileSize.h, 256.0, "tileSize h is set correctly");
+
+                map.setCenter(new OpenLayers.LonLat(-97.0, 38.0), 6);
+                
+                t.eq(layer0.tileOrigin.lon, -175, "tileOrigin.lat updated correctly when zoom changed"); 
+                t.eq(layer0.tileOrigin.lat, 85, "tileOrigin.lat updated correctly when zoom changed");                
+                t.eq(layer0.tileSize.w, 512.0, "tileSize w updated correctly when zoom changed");
+                t.eq(layer0.tileSize.h, 512.0, "tileSize h updated correctly when zoom changed");                    
+
+                map.destroy();
+            }
+
+            function test_clearTiles (t) {
+                t.plan(1);
+                var map = new OpenLayers.Map('map');
+
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });
+                
+                map.addLayer(layer1);
+                map.setCenter(new OpenLayers.LonLat(0,0));
+
+                //grab a reference to one of the tiles
+                var tile = layer1.grid[0][0];        
+
+                layer1.clearGrid();
+
+                t.ok( layer1.grid != null, "layer.grid does not get nullified" );
+                map.destroy();
+            }
+
+            function test_getTilesBounds(t) {
+                t.plan(1);
+                var layer1 = new OpenLayers.Layer.WMTS({ 
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });
+                var bl = {bounds: new OpenLayers.Bounds(1,2,0,0)};
+                var tr = {bounds: new OpenLayers.Bounds(0,0,3,4)};
+                layer1.grid = [[6, tr],[bl, 7]];
+                var bounds = layer1.getTilesBounds();            
+                var testBounds = new OpenLayers.Bounds(1,2,3,4);                
+                t.ok(bounds.equals(testBounds), "correct bounds");                
+            }
+
+            function test_getResolution(t) {
+                t.plan(1);
+                var map = new OpenLayers.Map('map');
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });
+                map.addLayer(layer1);
+                map.zoom = 5;
+                t.eq(layer1.getResolution(), 0.0439453125, "getResolution() returns correct value");
+                map.destroy();
+            }
+
+            function test_getZoomForExtent(t) {
+                t.plan(2);
+                var bounds, zoom;
+
+                var map = new OpenLayers.Map('map');
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });                                
+                map.addLayer(layer1);
+                bounds = new OpenLayers.Bounds(10,10,12,12);
+                zoom = layer1.getZoomForExtent(bounds);
+                t.eq(zoom, 8, "correct value for (10,10,12,12)");
+                bounds = new OpenLayers.Bounds(10,10,100,100);
+                zoom = layer1.getZoomForExtent(bounds);
+                t.eq(zoom, 3, "correct value (10,10,100,100)");
+                map.destroy();
+            }   
+
+            function test_getURL(t) {
+                t.plan(2);
+                var xml = document.getElementById("capabilities").firstChild.nodeValue;
+                var doc = new OpenLayers.Format.XML().read(xml);
+                var obj = new OpenLayers.Format.WMTSCapabilities().read(doc);
+            
+                var layer0 = new OpenLayers.Layer.WMTS({
+                    name: "GeoWebCache USA WMTS", 
+                    url: "http://example.com/geowebcache-1.2.2/service/wmts/",
+                    layer: "arcgis-online-wms",
+                    style: "foo",
+                    matrixSet: "arcgis-online-wgs84",                
+                    format: "image/png",
+                    requestEncoding: "KVP",
+                    maxResolution: 0.3521969032857032,
+                    numZoomLevels: 7,
+                    matrixIds: obj.contents.tileMatrixSets["arcgis-online-wgs84"].matrixIds
+                }); 
+                 
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    format: "image/jpeg",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST",
+                    isBaseLayer: false            
+                });     
+
+                var options = {
+                    controls: [            
+                        new OpenLayers.Control.LayerSwitcher(),
+                        new OpenLayers.Control.Navigation(),   
+                        new OpenLayers.Control.PanZoom()
+                    ],
+                    projection: "EPSG:4326",                                    
+                    maxResolution: 0.3515625,
+                    maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90)
+                };    
+                var map = new OpenLayers.Map('map', options);
+                map.addLayers([layer0,layer1]);
+                map.setCenter(new OpenLayers.LonLat(-97.0, 38.0), 1);
+                var tileurl0 = layer0.getURL(new OpenLayers.Bounds(-135.0, 0.0, -90.0, 45.0));
+                t.ok(OpenLayers.Util.isEquivalentUrl(tileurl0, "http://example.com/geowebcache-1.2.2/service/wmts/?LAYER=arcgis-online-wms&STYLE=foo&TILEMATRIXSET=arcgis-online-wgs84&FORMAT=image%2Fpng&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&TILEMATRIX=arcgis-online-wgs84%3A1&TILEROW=1&TILECOL=1"), "layer0 getURL returns correct url");
+
+                var tileurl1 = layer1.getURL(new OpenLayers.Bounds(-180.0, 0.0, -90.0, 90.0));
+                t.eq(tileurl1, "http://example.com/wmts/1.0.0/world/blue_marble/arcgis_online/1/0/0.jpg", "layer1 getURL returns correct url");                                        
+                map.destroy();
+            }
+            
+            function test_destroy (t) {
+                t.plan(3);
+                var map = new OpenLayers.Map('map');
+                var layer1 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });    
+                map.addLayer(layer1);
+                layer1.destroy();
+                t.eq( layer1.grid, null, "layer.grid is null after destroy" );
+                t.eq( layer1.tileSize, null, "layer.tileSize is null after destroy" );
+
+                //test with tile creation
+                var layer2 = new OpenLayers.Layer.WMTS({
+                    name: "Blue Marble WMTS",  
+                    url: "http://example.com/wmts/",
+                    layer: "world",
+                    style: "blue_marble",
+                    matrixSet: "arcgis_online",
+                    tileSize: new OpenLayers.Size(512, 512),            
+                    requestEncoding: "REST"            
+                });    
+                map.addLayer(layer2);
+                map.setCenter(new OpenLayers.LonLat(0,0), 5);
+                //grab a reference to one of the tiles
+                var tile = layer2.grid[0][0];        
+
+                layer2.destroy();
+
+                t.ok( layer2.grid == null, "tiles appropriately destroyed");
+                map.destroy();
+            }    
+        </script>
+    </head>
+    <body>
+        <div id="map" style="width:1024px;height:512px;"></div>
+        <div id="capabilities"><!--
+<Capabilities xmlns="http://www.opengis.net/wmts/1.0"
+xmlns:ows="http://www.opengis.net/ows/1.1"
+xmlns:xlink="http://www.w3.org/1999/xlink"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://geowebcache.org/schema/opengis/wmts/1.0.0/wmtsGetCapabilities_response.xsd"
+version="1.0.0">
+<ows:ServiceIdentification>
+  <ows:Title>Web Map Tile Service - GeoWebCache</ows:Title>
+  <ows:ServiceType>OGC WMTS</ows:ServiceType>
+  <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
+</ows:ServiceIdentification>
+<ows:ServiceProvider>
+  <ows:ProviderName>http://example.com/geowebcache-1.2.2/service/wmts</ows:ProviderName>
+  <ows:ProviderSite xlink:href="http://example.com/geowebcache-1.2.2/service/wmts" />
+  <ows:ServiceContact>
+    <ows:IndividualName>GeoWebCache User</ows:IndividualName>
+  </ows:ServiceContact>
+</ows:ServiceProvider>
+<ows:OperationsMetadata>
+  <ows:Operation name="GetCapabilities">
+    <ows:DCP>
+      <ows:HTTP>
+        <ows:Get xlink:href="http://example.com/geowebcache-1.2.2/service/wmts?">
+          <ows:Constraint name="GetEncoding">
+            <ows:AllowedValues>
+              <ows:Value>KVP</ows:Value>
+            </ows:AllowedValues>
+          </ows:Constraint>
+        </ows:Get>
+      </ows:HTTP>
+    </ows:DCP>
+  </ows:Operation>
+  <ows:Operation name="GetTile">
+    <ows:DCP>
+      <ows:HTTP>
+        <ows:Get xlink:href="http://example.com/geowebcache-1.2.2/service/wmts?">
+          <ows:Constraint name="GetEncoding">
+            <ows:AllowedValues>
+              <ows:Value>KVP</ows:Value>
+            </ows:AllowedValues>
+          </ows:Constraint>
+        </ows:Get>
+      </ows:HTTP>
+    </ows:DCP>
+  </ows:Operation>
+  <ows:Operation name="GetFeatureInfo">
+    <ows:DCP>
+      <ows:HTTP>
+        <ows:Get xlink:href="http://example.com/geowebcache-1.2.2/service/wmts?">
+          <ows:Constraint name="GetEncoding">
+            <ows:AllowedValues>
+              <ows:Value>KVP</ows:Value>
+            </ows:AllowedValues>
+          </ows:Constraint>
+        </ows:Get>
+      </ows:HTTP>
+    </ows:DCP>
+  </ows:Operation>
+</ows:OperationsMetadata>
+<Contents>
+  <Layer>
+    <ows:Title>arcgis-online-wms</ows:Title>
+    <ows:Abstract>arcgis-online-wms</ows:Abstract>
+    <ows:WGS84BoundingBox>
+      <ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>
+      <ows:UpperCorner>180.0 90.0</ows:UpperCorner>
+    </ows:WGS84BoundingBox>
+    <ows:Identifier>arcgis-online-wms</ows:Identifier>
+    <Style isDefault="true">
+      <ows:Identifier>_null</ows:Identifier>
+    </Style>
+    <Format>image/png</Format>
+    <Format>image/jpeg</Format>
+    <TileMatrixSetLink>      <TileMatrixSet>arcgis-online-wgs84</TileMatrixSet>
+    </TileMatrixSetLink>  </Layer>
+  <TileMatrixSet>
+    <ows:Identifier>EPSG:4326</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:0</ows:Identifier>
+      <ScaleDenominator>2.795411320143589E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:1</ows:Identifier>
+      <ScaleDenominator>1.3977056600717944E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:2</ows:Identifier>
+      <ScaleDenominator>6.988528300358972E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8</MatrixWidth>
+      <MatrixHeight>4</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:3</ows:Identifier>
+      <ScaleDenominator>3.494264150179486E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16</MatrixWidth>
+      <MatrixHeight>8</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:4</ows:Identifier>
+      <ScaleDenominator>1.747132075089743E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32</MatrixWidth>
+      <MatrixHeight>16</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:5</ows:Identifier>
+      <ScaleDenominator>8735660.375448715</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>64</MatrixWidth>
+      <MatrixHeight>32</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:6</ows:Identifier>
+      <ScaleDenominator>4367830.1877243575</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>128</MatrixWidth>
+      <MatrixHeight>64</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:7</ows:Identifier>
+      <ScaleDenominator>2183915.0938621787</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>256</MatrixWidth>
+      <MatrixHeight>128</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:8</ows:Identifier>
+      <ScaleDenominator>1091957.5469310894</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>512</MatrixWidth>
+      <MatrixHeight>256</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:9</ows:Identifier>
+      <ScaleDenominator>545978.7734655447</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1024</MatrixWidth>
+      <MatrixHeight>512</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:10</ows:Identifier>
+      <ScaleDenominator>272989.38673277234</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2048</MatrixWidth>
+      <MatrixHeight>1024</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:11</ows:Identifier>
+      <ScaleDenominator>136494.69336638617</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4096</MatrixWidth>
+      <MatrixHeight>2048</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:12</ows:Identifier>
+      <ScaleDenominator>68247.34668319309</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8192</MatrixWidth>
+      <MatrixHeight>4096</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:13</ows:Identifier>
+      <ScaleDenominator>34123.67334159654</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16384</MatrixWidth>
+      <MatrixHeight>8192</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:14</ows:Identifier>
+      <ScaleDenominator>17061.83667079827</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32768</MatrixWidth>
+      <MatrixHeight>16384</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:15</ows:Identifier>
+      <ScaleDenominator>8530.918335399136</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>65536</MatrixWidth>
+      <MatrixHeight>32768</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:16</ows:Identifier>
+      <ScaleDenominator>4265.459167699568</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>131072</MatrixWidth>
+      <MatrixHeight>65536</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:17</ows:Identifier>
+      <ScaleDenominator>2132.729583849784</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>262144</MatrixWidth>
+      <MatrixHeight>131072</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:18</ows:Identifier>
+      <ScaleDenominator>1066.364791924892</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>524288</MatrixWidth>
+      <MatrixHeight>262144</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:19</ows:Identifier>
+      <ScaleDenominator>533.182395962446</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1048576</MatrixWidth>
+      <MatrixHeight>524288</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:20</ows:Identifier>
+      <ScaleDenominator>266.591197981223</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2097152</MatrixWidth>
+      <MatrixHeight>1048576</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:21</ows:Identifier>
+      <ScaleDenominator>133.2955989906115</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4194304</MatrixWidth>
+      <MatrixHeight>2097152</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:22</ows:Identifier>
+      <ScaleDenominator>66.64779949530575</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8388608</MatrixWidth>
+      <MatrixHeight>4194304</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:23</ows:Identifier>
+      <ScaleDenominator>33.323899747652874</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16777216</MatrixWidth>
+      <MatrixHeight>8388608</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:24</ows:Identifier>
+      <ScaleDenominator>16.661949873826437</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>33554432</MatrixWidth>
+      <MatrixHeight>16777216</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:25</ows:Identifier>
+      <ScaleDenominator>8.330974936913218</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>67108864</MatrixWidth>
+      <MatrixHeight>33554432</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:26</ows:Identifier>
+      <ScaleDenominator>4.165487468456609</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>134217728</MatrixWidth>
+      <MatrixHeight>67108864</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:27</ows:Identifier>
+      <ScaleDenominator>2.0827437342283046</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>268435456</MatrixWidth>
+      <MatrixHeight>134217728</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:28</ows:Identifier>
+      <ScaleDenominator>1.0413718671141523</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>536870912</MatrixWidth>
+      <MatrixHeight>268435456</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:29</ows:Identifier>
+      <ScaleDenominator>0.5206859335570762</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1073741824</MatrixWidth>
+      <MatrixHeight>536870912</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:4326:30</ows:Identifier>
+      <ScaleDenominator>0.2603429667785381</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2147483648</MatrixWidth>
+      <MatrixHeight>1073741824</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+  <TileMatrixSet>
+    <ows:Identifier>arcgis-online-epsg102113</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::102113</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:0</ows:Identifier>
+      <ScaleDenominator>5.590822639285715E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:1</ows:Identifier>
+      <ScaleDenominator>2.7954113196428573E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:2</ows:Identifier>
+      <ScaleDenominator>1.3977056598214287E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4</MatrixWidth>
+      <MatrixHeight>4</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:3</ows:Identifier>
+      <ScaleDenominator>6.988528299107143E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8</MatrixWidth>
+      <MatrixHeight>8</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:4</ows:Identifier>
+      <ScaleDenominator>3.494264149553572E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16</MatrixWidth>
+      <MatrixHeight>16</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:5</ows:Identifier>
+      <ScaleDenominator>1.747132074776786E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32</MatrixWidth>
+      <MatrixHeight>32</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:6</ows:Identifier>
+      <ScaleDenominator>8735660.37388393</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>64</MatrixWidth>
+      <MatrixHeight>64</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:7</ows:Identifier>
+      <ScaleDenominator>4367830.186941965</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>128</MatrixWidth>
+      <MatrixHeight>128</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Abstract>The grid was not well-defined, the scale therefore assumes 1m per map unit.</ows:Abstract>      <ows:Identifier>arcgis-online-epsg102113:8</ows:Identifier>
+      <ScaleDenominator>2183915.0934709823</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.00375083392E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>256</MatrixWidth>
+      <MatrixHeight>256</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+  <TileMatrixSet>
+    <ows:Identifier>GlobalCRS84Scale</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:0</ows:Identifier>
+      <ScaleDenominator>5.0000000000000006E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:1</ows:Identifier>
+      <ScaleDenominator>2.5000000000000003E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>3</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:2</ows:Identifier>
+      <ScaleDenominator>1.0000000000000001E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>6</MatrixWidth>
+      <MatrixHeight>3</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:3</ows:Identifier>
+      <ScaleDenominator>5.000000000000001E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>12</MatrixWidth>
+      <MatrixHeight>6</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:4</ows:Identifier>
+      <ScaleDenominator>2.5000000000000004E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>23</MatrixWidth>
+      <MatrixHeight>12</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:5</ows:Identifier>
+      <ScaleDenominator>1.0E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>56</MatrixWidth>
+      <MatrixHeight>28</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:6</ows:Identifier>
+      <ScaleDenominator>5000000.0</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>112</MatrixWidth>
+      <MatrixHeight>56</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:7</ows:Identifier>
+      <ScaleDenominator>2500000.0</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>224</MatrixWidth>
+      <MatrixHeight>112</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:8</ows:Identifier>
+      <ScaleDenominator>1000000.0000000001</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>560</MatrixWidth>
+      <MatrixHeight>280</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:9</ows:Identifier>
+      <ScaleDenominator>500000.00000000006</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1119</MatrixWidth>
+      <MatrixHeight>560</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:10</ows:Identifier>
+      <ScaleDenominator>250000.00000000003</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2237</MatrixWidth>
+      <MatrixHeight>1119</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:11</ows:Identifier>
+      <ScaleDenominator>100000.00000000001</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>5591</MatrixWidth>
+      <MatrixHeight>2796</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:12</ows:Identifier>
+      <ScaleDenominator>50000.00000000001</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>11182</MatrixWidth>
+      <MatrixHeight>5591</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:13</ows:Identifier>
+      <ScaleDenominator>25000.000000000004</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>22364</MatrixWidth>
+      <MatrixHeight>11182</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:14</ows:Identifier>
+      <ScaleDenominator>10000.000000000002</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>55909</MatrixWidth>
+      <MatrixHeight>27955</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:15</ows:Identifier>
+      <ScaleDenominator>5000.000000000001</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>111817</MatrixWidth>
+      <MatrixHeight>55909</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:16</ows:Identifier>
+      <ScaleDenominator>2500.0000000000005</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>223633</MatrixWidth>
+      <MatrixHeight>111817</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:17</ows:Identifier>
+      <ScaleDenominator>1000.0000000000002</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>559083</MatrixWidth>
+      <MatrixHeight>279542</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:18</ows:Identifier>
+      <ScaleDenominator>500.0000000000001</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1118165</MatrixWidth>
+      <MatrixHeight>559083</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:19</ows:Identifier>
+      <ScaleDenominator>250.00000000000006</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2236330</MatrixWidth>
+      <MatrixHeight>1118165</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Scale:20</ows:Identifier>
+      <ScaleDenominator>100.00000000000003</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>5590823</MatrixWidth>
+      <MatrixHeight>2795412</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+  <TileMatrixSet>
+    <ows:Identifier>EPSG:900913</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::900913</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:0</ows:Identifier>
+      <ScaleDenominator>5.590822639508929E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:1</ows:Identifier>
+      <ScaleDenominator>2.7954113197544646E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:2</ows:Identifier>
+      <ScaleDenominator>1.3977056598772323E8</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4</MatrixWidth>
+      <MatrixHeight>4</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:3</ows:Identifier>
+      <ScaleDenominator>6.988528299386162E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8</MatrixWidth>
+      <MatrixHeight>8</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:4</ows:Identifier>
+      <ScaleDenominator>3.494264149693081E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16</MatrixWidth>
+      <MatrixHeight>16</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:5</ows:Identifier>
+      <ScaleDenominator>1.7471320748465404E7</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32</MatrixWidth>
+      <MatrixHeight>32</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:6</ows:Identifier>
+      <ScaleDenominator>8735660.374232702</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>64</MatrixWidth>
+      <MatrixHeight>64</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:7</ows:Identifier>
+      <ScaleDenominator>4367830.187116351</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>128</MatrixWidth>
+      <MatrixHeight>128</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:8</ows:Identifier>
+      <ScaleDenominator>2183915.0935581755</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>256</MatrixWidth>
+      <MatrixHeight>256</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:9</ows:Identifier>
+      <ScaleDenominator>1091957.5467790877</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>512</MatrixWidth>
+      <MatrixHeight>512</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:10</ows:Identifier>
+      <ScaleDenominator>545978.7733895439</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1024</MatrixWidth>
+      <MatrixHeight>1024</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:11</ows:Identifier>
+      <ScaleDenominator>272989.38669477194</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2048</MatrixWidth>
+      <MatrixHeight>2048</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:12</ows:Identifier>
+      <ScaleDenominator>136494.69334738597</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4096</MatrixWidth>
+      <MatrixHeight>4096</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:13</ows:Identifier>
+      <ScaleDenominator>68247.34667369298</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8192</MatrixWidth>
+      <MatrixHeight>8192</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:14</ows:Identifier>
+      <ScaleDenominator>34123.67333684649</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16384</MatrixWidth>
+      <MatrixHeight>16384</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:15</ows:Identifier>
+      <ScaleDenominator>17061.836668423246</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32768</MatrixWidth>
+      <MatrixHeight>32768</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:16</ows:Identifier>
+      <ScaleDenominator>8530.918334211623</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>65536</MatrixWidth>
+      <MatrixHeight>65536</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:17</ows:Identifier>
+      <ScaleDenominator>4265.4591671058115</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>131072</MatrixWidth>
+      <MatrixHeight>131072</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:18</ows:Identifier>
+      <ScaleDenominator>2132.7295835529058</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>262144</MatrixWidth>
+      <MatrixHeight>262144</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:19</ows:Identifier>
+      <ScaleDenominator>1066.3647917764529</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>524288</MatrixWidth>
+      <MatrixHeight>524288</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:20</ows:Identifier>
+      <ScaleDenominator>533.1823958882264</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1048576</MatrixWidth>
+      <MatrixHeight>1048576</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:21</ows:Identifier>
+      <ScaleDenominator>266.5911979441132</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2097152</MatrixWidth>
+      <MatrixHeight>2097152</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:22</ows:Identifier>
+      <ScaleDenominator>133.2955989720566</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4194304</MatrixWidth>
+      <MatrixHeight>4194304</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:23</ows:Identifier>
+      <ScaleDenominator>66.6477994860283</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8388608</MatrixWidth>
+      <MatrixHeight>8388608</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:24</ows:Identifier>
+      <ScaleDenominator>33.32389974301415</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16777216</MatrixWidth>
+      <MatrixHeight>16777216</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:25</ows:Identifier>
+      <ScaleDenominator>16.661949871507076</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>33554432</MatrixWidth>
+      <MatrixHeight>33554432</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:26</ows:Identifier>
+      <ScaleDenominator>8.330974935753538</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>67108864</MatrixWidth>
+      <MatrixHeight>67108864</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:27</ows:Identifier>
+      <ScaleDenominator>4.165487467876769</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>134217728</MatrixWidth>
+      <MatrixHeight>134217728</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:28</ows:Identifier>
+      <ScaleDenominator>2.0827437339383845</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>268435456</MatrixWidth>
+      <MatrixHeight>268435456</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:29</ows:Identifier>
+      <ScaleDenominator>1.0413718669691923</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>536870912</MatrixWidth>
+      <MatrixHeight>536870912</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>EPSG:900913:30</ows:Identifier>
+      <ScaleDenominator>0.5206859334845961</ScaleDenominator>
+      <TopLeftCorner>2.0037508E7 -2.003750834E7</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1073741824</MatrixWidth>
+      <MatrixHeight>1073741824</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+  <TileMatrixSet>
+    <ows:Identifier>arcgis-online-wgs84</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:0</ows:Identifier>
+      <ScaleDenominator>1.3977056600717944E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>4</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:1</ows:Identifier>
+      <ScaleDenominator>6.988528300358972E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>8</MatrixWidth>
+      <MatrixHeight>4</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:2</ows:Identifier>
+      <ScaleDenominator>3.494264150179486E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16</MatrixWidth>
+      <MatrixHeight>8</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:3</ows:Identifier>
+      <ScaleDenominator>1.747132075089743E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>32</MatrixWidth>
+      <MatrixHeight>16</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:4</ows:Identifier>
+      <ScaleDenominator>8735660.375448715</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>64</MatrixWidth>
+      <MatrixHeight>32</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:5</ows:Identifier>
+      <ScaleDenominator>4367830.1877243575</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>128</MatrixWidth>
+      <MatrixHeight>64</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>arcgis-online-wgs84:6</ows:Identifier>
+      <ScaleDenominator>2183915.0938621787</ScaleDenominator>
+      <TopLeftCorner>85 -175</TopLeftCorner>
+      <TileWidth>512</TileWidth>
+      <TileHeight>512</TileHeight>
+      <MatrixWidth>256</MatrixWidth>
+      <MatrixHeight>128</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+  <TileMatrixSet>
+    <ows:Identifier>GlobalCRS84Pixel</ows:Identifier>
+    <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:0</ows:Identifier>
+      <ScaleDenominator>7.951392199519542E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:1</ows:Identifier>
+      <ScaleDenominator>3.975696099759771E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>2</MatrixWidth>
+      <MatrixHeight>1</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:2</ows:Identifier>
+      <ScaleDenominator>1.9878480498798856E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>3</MatrixWidth>
+      <MatrixHeight>2</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:3</ows:Identifier>
+      <ScaleDenominator>1.325232033253257E8</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>5</MatrixWidth>
+      <MatrixHeight>3</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:4</ows:Identifier>
+      <ScaleDenominator>6.626160166266285E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>9</MatrixWidth>
+      <MatrixHeight>5</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:5</ows:Identifier>
+      <ScaleDenominator>3.3130800831331424E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>17</MatrixWidth>
+      <MatrixHeight>9</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:6</ows:Identifier>
+      <ScaleDenominator>1.325232033253257E7</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>43</MatrixWidth>
+      <MatrixHeight>22</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:7</ows:Identifier>
+      <ScaleDenominator>6626160.166266285</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>85</MatrixWidth>
+      <MatrixHeight>43</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:8</ows:Identifier>
+      <ScaleDenominator>3313080.0831331424</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>169</MatrixWidth>
+      <MatrixHeight>85</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:9</ows:Identifier>
+      <ScaleDenominator>1656540.0415665712</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>338</MatrixWidth>
+      <MatrixHeight>169</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:10</ows:Identifier>
+      <ScaleDenominator>552180.0138555238</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1013</MatrixWidth>
+      <MatrixHeight>507</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:11</ows:Identifier>
+      <ScaleDenominator>331308.00831331423</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>1688</MatrixWidth>
+      <MatrixHeight>844</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:12</ows:Identifier>
+      <ScaleDenominator>110436.00277110476</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>5063</MatrixWidth>
+      <MatrixHeight>2532</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:13</ows:Identifier>
+      <ScaleDenominator>55218.00138555238</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>10125</MatrixWidth>
+      <MatrixHeight>5063</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:14</ows:Identifier>
+      <ScaleDenominator>33130.80083133143</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>16875</MatrixWidth>
+      <MatrixHeight>8438</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:15</ows:Identifier>
+      <ScaleDenominator>11043.600277110474</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>50625</MatrixWidth>
+      <MatrixHeight>25313</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:16</ows:Identifier>
+      <ScaleDenominator>3313.080083133142</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>168750</MatrixWidth>
+      <MatrixHeight>84375</MatrixHeight>
+    </TileMatrix>
+    <TileMatrix>
+      <ows:Identifier>GlobalCRS84Pixel:17</ows:Identifier>
+      <ScaleDenominator>1104.3600277110472</ScaleDenominator>
+      <TopLeftCorner>90.0 -180.0</TopLeftCorner>
+      <TileWidth>256</TileWidth>
+      <TileHeight>256</TileHeight>
+      <MatrixWidth>506250</MatrixWidth>
+      <MatrixHeight>253125</MatrixHeight>
+    </TileMatrix>
+  </TileMatrixSet>
+</Contents>
+<ServiceMetadataURL xlink:href="http://example.com/geowebcache-1.2.2/service/wmts?REQUEST=getcapabilities&amp;VERSION=1.0.0"/>
+</Capabilities>
+        -->
+        </div>
+    </body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Layer/XYZ.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer/XYZ.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer/XYZ.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -148,6 +148,72 @@
         map.destroy();
     }
 
+    function test_Layer_XYZ_serverResolutions(t) {
+        t.plan(2);
+
+        var map = new OpenLayers.Map('map', {
+            resolutions: [13,11]
+        });
+
+        var layer = new OpenLayers.Layer.XYZ(name, url, options);
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0,0), 1);
+
+        var tileurl = layer.getURL(new OpenLayers.Bounds(0,0,0,0));
+        var level = parseInt(tileurl.split('/')[7]);
+        t.eq(map.getZoom(), level, "Tile zoom level is correct without serverResolutions");
+
+        layer.serverResolutions = [14,13,12,11,10];
+        tileurl = layer.getURL(new OpenLayers.Bounds(0,0,0,0));
+        level = parseInt(tileurl.split('/')[7]);
+        var res = map.getResolution();
+        var gotLevel = OpenLayers.Util.indexOf(layer.serverResolutions, res);
+        t.eq(gotLevel, level, "Tile zoom level is correct with serverResolutions");
+
+        map.destroy();
+    }
+
+    function test_zoomOffset(t) {
+
+        t.plan(2);
+        
+        var offset;
+        
+        // test offset of 2
+        offset = 2;
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            maxResolution: OpenLayers.Map.prototype.maxResolution / Math.pow(2, offset)
+        });
+        var layer = new OpenLayers.Layer.XYZ(name, url, {zoomOffset: offset});
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0,0), 7);
+
+        var tileurl = layer.getURL(new OpenLayers.Bounds(3.515625,45,4.21875,45.703125));
+        t.eq(tileurl, "http://labs.metacarta.com/wms-c/Basic.py/1.0.0/basic/9/261/63.png", "correct URL for offset of 2");
+
+        map.destroy();
+
+        // test offset of -1
+        offset = -1;
+        
+        var map = new OpenLayers.Map({
+            div: "map",
+            maxResolution: OpenLayers.Map.prototype.maxResolution / Math.pow(2, offset)
+        });
+        var layer = new OpenLayers.Layer.XYZ(name, url, {zoomOffset: offset});
+        map.addLayer(layer);
+        map.setCenter(new OpenLayers.LonLat(0,0), 10);
+
+        var tileurl = layer.getURL(new OpenLayers.Bounds(3.515625,45,4.21875,45.703125));
+        t.eq(tileurl, "http://labs.metacarta.com/wms-c/Basic.py/1.0.0/basic/9/261/63.png", "correct URL for offset of -1");
+
+        map.destroy();
+
+
+    }
+
     function test_Layer_XYZ_destroy (t) {
 
         t.plan( 3 );
@@ -173,7 +239,20 @@
         map.destroy();
     }
     
+    function test_clone(t) {
+        t.plan(2);
+        
+        var clone;
+        
+        layer = new OpenLayers.Layer.XYZ(name, url, options);
+        clone = layer.clone();
+        t.ok(clone instanceof OpenLayers.Layer.XYZ, "clone is a Layer.XYZ instance");
 
+        layer = new OpenLayers.Layer.OSM();
+        clone = layer.clone();
+        t.ok(clone instanceof OpenLayers.Layer.OSM, "clone is a Layer.OSM instance");
+    }
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Layer.html
===================================================================
--- sandbox/ahocevar/playground/tests/Layer.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Layer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -35,13 +35,15 @@
         t.ok( layer.options instanceof Object, "layer.options correctly initialized as a non-null Object" );
     }
 
+
     function test_Layer_clone (t) {
-        t.plan( 8 );
+        t.plan( 7 );
         
         var mapone = new OpenLayers.Map('map'); 
-        var options = { chicken: 151, foo: "bar", maxResolution: "auto" };
+        var options = { chicken: 151, foo: "bar", maxResolution: "auto", visibility: false };
         var layer = new OpenLayers.Layer('Test Layer', options);
         mapone.addLayer(layer);
+        layer.setVisibility(true);
 
         // randomly assigned property
         layer.chocolate = 5;
@@ -58,12 +60,11 @@
         t.ok( ((clone.options["chicken"] == 151) && (clone.options["foo"] == "bar")), "clone.options correctly set" );
         t.eq(clone.chocolate, 5, "correctly copied randomly assigned property");
 
+        t.eq(clone.visibility, true, "visibility correctly cloned");
+        
         layer.addOptions({chicken:152});
         t.eq(clone.options["chicken"], 151, "made a clean copy of options");        
 
-        t.ok( (layer.maxResolution != clone.maxResolution), "maxresolution of clone reset to new map div");
-        t.ok( (layer.minResolution != clone.minResolution), "minresolution of clone reset to new map div");
-        
         mapone.destroy();
         maptwo.destroy();
     }
@@ -81,26 +82,92 @@
 
     function test_Layer_addOptions (t) {
         
-        t.plan( 4 );
+        t.plan( 19 );
 
+        var map = new OpenLayers.Map("map");
         var options = { chicken: 151, foo: "bar" };
         var layer = new OpenLayers.Layer('Test Layer', options);
+        map.addLayer(layer);
 
         layer.addOptions({bark:55, chicken: 171});
-
         t.eq(layer.bark, 55, "addOptions() assigns new option correctly to Layer");
         t.eq(layer.options.bark, 55, "addOptions() adds new option correctly to backup");
 
         t.eq(layer.chicken, 171, "addOptions() overwrites option correctly to Layer");
         t.eq(layer.options.chicken, 171, "addOptions() overwrites option correctly to backup");
 
+        var log;
+        layer.initResolutions = function() {
+            log++;
+        };
+        log = 0;
+        layer.addOptions({bark: 56});
+        t.eq(log, 0, "addOptions doesn't call initResolutions when not given a resolution option");
+
+        log = 0;
+        layer.addOptions({scales: [1, 2]});
+        t.eq(log, 1, "addOptions calls initResolutions when given scales");
+
+        log = 0;
+        layer.addOptions({resolutions: [1, 2]});
+        t.eq(log, 1, "addOptions calls initResolutions when given resolutions");
+
+        log = 0;
+        layer.addOptions({minScale: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given minScale");
+
+        log = 0;
+        layer.addOptions({maxScale: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given maxScale");
+
+        log = 0;
+        layer.addOptions({minResolution: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given minResolution");
+
+        log = 0;
+        layer.addOptions({maxResolution: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given maxResolution");
+
+        log = 0;
+        layer.addOptions({numZoomLevels: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given numZoomLevels");
+
+        log = 0;
+        layer.addOptions({maxZoomLevel: 4});
+        t.eq(log, 1, "addOptions calls initResolutions when given maxZoomLevel");
+
+        log = 0;
+        layer.addOptions({projection: new OpenLayers.Projection("EPSG:900913")});
+        t.eq(log, 1, "addOptions calls initResolutions when given projection");
+
+        log = 0;
+        layer.addOptions({units: "m"});
+        t.eq(log, 1, "addOptions calls initResolutions when given units");
+
+        log = 0;
+        layer.addOptions({minExtent: new OpenLayers.Bounds(0, 0, 0, 0)});
+        t.eq(log, 1, "addOptions calls initResolutions when given minExtent");
+
+        log = 0;
+        layer.addOptions({maxExtent: new OpenLayers.Bounds(0, 0, 0, 0)});
+        t.eq(log, 1, "addOptions calls initResolutions when given maxExtent");
+
+        layer.projection = null;
+        layer.addOptions({projection: "EPSG:900913"});
+        t.ok(layer.projection instanceof OpenLayers.Projection,
+             "addOptions creates a Projection object when given a projection string");
+
+        map.removeLayer(layer);
+        log = 0;
+        layer.addOptions({minExtent: new OpenLayers.Bounds(0, 0, 0, 0)});
+        t.eq(log, 0, "addOptions doesn't call initResolutions when layer is not in map");
     }
     
     function test_Layer_StandardOptionsAccessors (t) {
 
         t.plan( 4 );
 
-        var projection = "chicken";
+        var projection = "EPSG:4326";
         var maxExtent = new OpenLayers.Bounds(50,50,100,100);
         var maxResolution = 1.5726;
         var numZoomLevels = 11;
@@ -113,7 +180,7 @@
 
         var layer = new OpenLayers.Layer('Test Layer', options);
 
-        t.eq(layer.projection, projection, "projection set correctly");
+        t.eq(layer.projection.getCode(), projection, "projection set correctly");
         t.ok(layer.maxExtent.equals(maxExtent), "maxExtent set correctly");
         t.eq(layer.maxResolution, maxResolution, "maxResolution set correctly");
         t.eq(layer.numZoomLevels, numZoomLevels, "numZoomLevels set correctly");
@@ -144,85 +211,312 @@
         layer2.destroy();
     }
 
-    function test_Layer_initResolutions(t) {
-        t.plan(15);
-        var map = new OpenLayers.Map("map");
-        var options, layer;
-        
-        // tests for minResolution, maxResolution, and numZoomLevels
-        options = {
-            minResolution: 1.5,
-            maxResolution: 10.5,
-            numZoomLevels: 5,
-            map: map
-        };
-        layer = new OpenLayers.Layer("test", options);
-        layer.initResolutions();
-        t.eq(layer.minResolution.toPrecision(6), (1.5).toPrecision(6),
-             "(with numZoomLevels) layer minResolution preserved");
-        t.eq(layer.maxResolution.toPrecision(6), (10.5).toPrecision(6),
-             "(with numZoomLevels) layer maxResolution preserved");
-        t.eq(layer.numZoomLevels, 5, "(with numZoomLevels) layer numZoomLevels preserved");
-        t.eq(layer.alwaysInRange, false, "Always in range is set to false due to passed options.")        
+    function test_initResolutions_alwaysInRange(t) {
+        t.plan(3);
 
-        // three tests for minResolution, and maxResolution
-        options = {
-            minResolution: 1.5,
-            maxResolution: 10.5,
-            map: map
-        };
-        layer = new OpenLayers.Layer("test", options);
-        layer.initResolutions();
-        t.eq(layer.minResolution.toPrecision(6), (1.5).toPrecision(6),
-             "(without numZoomLevels) layer minResolution preserved");
-        t.eq(layer.maxResolution.toPrecision(6), (10.5).toPrecision(6),
-             "(without numZoomLevels) layer maxResolution preserved");
-        t.eq(layer.numZoomLevels, 3, "(without numZoomLevels) layer numZoomLevels calculated");
-        
-        // three tests for minScale, maxScale, and numZoomLevels
-        options = {
-            minScale: 105,
-            maxScale: 15,
-            numZoomLevels: 10,
-            map: map
-        };
-        layer = new OpenLayers.Layer("test", options);
-        layer.initResolutions();
-        t.eq(layer.minScale.toPrecision(6), (105).toPrecision(6),
-             "(with numZoomLevels) layer minScale preserved");
-        t.eq(layer.maxScale.toPrecision(6), (15).toPrecision(6),
-             "(with numZoomLevels) layer maxScale preserved");
-        t.eq(layer.numZoomLevels, 10, "(with numZoomLevels) layer numZoomLevels preserved");
-        
-        // three tests for minScale, and maxScale
-        options = {
-            minScale: 1555,
-            maxScale: 155,
-            map: map
-        };
-        layer = new OpenLayers.Layer("test", options);
-        layer.initResolutions();
-        t.eq(layer.minScale.toPrecision(6), (1555).toPrecision(6),
-             "(without numZoomLevels) layer minScale preserved");
-        t.eq(layer.maxScale.toPrecision(6), (155).toPrecision(6),
-             "(without numZoomLevels) layer maxScale preserved");
-        t.eq(layer.numZoomLevels, 4, "(without numZoomLevels) layer numZoomLevels calculated");
-        
-        layer = new OpenLayers.Layer("test", {'projection': 'EPSG:4326', 'map': map});
-        layer.initResolutions();
-        t.eq(layer.alwaysInRange, true, "always in range true if only get projection.");     
-        
+        var map, layer;
+
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer("test", {maxResolution: 80, minResolution: 10});
+        map.addLayer(layer);
+        t.eq(layer.alwaysInRange, false,
+             "alwaysInRange set to false due to passed options");
+        map.destroy();
+
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer("test", {projection: "EPSG:4326"});
+        map.addLayer(layer);
+        t.eq(layer.alwaysInRange, true,
+             "alwaysInRange true if only get projection.");
+        map.destroy();
+
+        map = new OpenLayers.Map("map");
         OpenLayers.Layer.prototype.alwaysInRange = false;
-        layer = new OpenLayers.Layer("test", {'projection': 'EPSG:4326', 'map': map});
-        layer.initResolutions();
-        t.eq(layer.alwaysInRange, false, "always in range true if overridden on prototype.");     
+        layer = new OpenLayers.Layer("test", {'projection': 'EPSG:4326'});
+        map.addLayer(layer);
+        t.eq(layer.alwaysInRange, false,
+             "alwaysInRange true if overridden on prototype.");
         OpenLayers.Layer.prototype.alwaysInRange = null;
-
         map.destroy();
-        
-        
     }
 
+    function test_initResolutions_resolutions(t) {
+
+        function initResolutionsTest(
+            id, mapOptions, layerOptions,
+            expectedResolutions, expectedMinResolution, expectedMaxResolution) {
+
+            // setup
+            var map = new OpenLayers.Map("map", mapOptions);
+            var layer = new OpenLayers.Layer(null, layerOptions);
+            map.addLayer(layer);
+
+            // make resolution assertions
+            t.eq(
+                layer.resolutions.length, expectedResolutions.length,
+                id + ": correct resolutions length"
+            );
+            // allow for floating point imprecision
+            var got, exp, same = true;
+            for (var i=0; i<expectedResolutions.length; ++i) {
+                got = layer.resolutions[i];
+                exp = expectedResolutions[i];
+                if (got.toFixed(10) !== exp.toFixed(10)) {
+                    t.fail(id + ": bad resolutions - index " + i + " got " + got + " but expected " + exp);
+                    same = false;
+                    break;
+                }
+            }
+            if (same) {
+                t.ok(true, id + ": correct resolutions");
+            }
+            t.eq(
+                layer.maxResolution, expectedMaxResolution,
+                id + ": maxResolution set"
+            );
+            t.eq(
+                layer.minResolution, expectedMinResolution,
+                id + ": minResolution set"
+            );
+
+            // teardown
+            map.destroy();
+        }
+
+        // each case is an array of id, map options, layer options, expected resolutions,
+        // expected min resolution, and expected max resolution
+        var cases = [[
+
+        /*
+         * Batch 1: map defaults and sensible layer options
+         */
+
+            "1.0",  null, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "1.1",  null, {resolutions: [400, 200, 100], minResolution: 150, maxResolution: 300},
+            [400, 200, 100], 150, 300
+        ], [
+            "1.2",  null, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "1.3",  null, {maxResolution: 4000, maxZoomLevel: 2},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "1.4",  null, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "1.5",  null, {minResolution: 40, maxZoomLevel: 2},
+            [160, 80, 40], 40, 160
+        ], [
+            "1.6", null, {minResolution: 10, maxResolution: 40},
+            [40, 20, 10], 10, 40
+        ], [
+            "1.7", null, {minResolution: 10, maxResolution: 40, numZoomLevels: 3},
+            [40, 20, 10], 10, 40
+        ], [
+            "1.8", null, {minResolution: 10, maxResolution: 40, maxZoomLevel: 2},
+            [40, 20, 10], 10, 40
+        ], [
+            "1.9",  null, {scales: [400000, 200000, 100000]},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.10",  null, {scales: [400000, 200000, 100000], minScale: 400000, maxScale: 100000},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.11",  null, {minScale: 400000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.12",  null, {minScale: 400000, maxZoomLevel: 2},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.13",  null, {maxScale: 100000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.14",  null, {maxScale: 100000, maxZoomLevel: 2},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.15",  null, {maxScale: 100000, minScale: 400000},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.16",  null, {maxScale: 100000, minScale: 400000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.17",  null, {maxScale: 100000, minScale: 400000, maxZoomLevel: 2},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "1.18",  null, {scales: [400000, 200000, 100000], units: "m"},
+            [141.11103491115225, 70.55551745557612, 35.27775872778806], 35.27775872778806, 141.11103491115225
+        ], [
+            "1.19",  null, {minScale: 400000, numZoomLevels: 3, units: "m"},
+            [141.11103491115225, 70.55551745557612, 35.27775872778806], 35.27775872778806, 141.11103491115225
+        ], [
+            "1.20",  null, {maxScale: 100000, numZoomLevels: 3, units: "m"},
+            [141.11103491115225, 70.55551745557612, 35.27775872778806], 35.27775872778806, 141.11103491115225
+        ], [
+
+        /*
+         * Batch 2: custom map options map and sensible layer options
+         */
+
+        /*
+         * Batch 2.1: resolutions set in the layer options
+         */
+            "2.1.0",  {resolutions: [300, 150]}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.1",  {numZoomLevels: 4}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.2",  {maxResolution: 300}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.3",  {minResolution: 300}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.4",  {scales: [4, 2, 1]}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.5",  {minScale: 4}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+            "2.1.6",  {maxScale: 4}, {resolutions: [400, 200, 100]},
+            [400, 200, 100], 100, 400
+        ], [
+        /*
+         * Batch 2.2: minResolution and maxResolution set in the layer options
+         */
+            "2.2.0",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48, numZoomLevels: 0},
+            [80, 40, 20, 10], 12, 48
+        ], [
+            "2.2.1",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48, numZoomLevels: -1},
+            [80, 40, 20, 10], 12, 48
+        ], [
+            "2.2.2",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48, numZoomLevels: null},
+            [80, 40, 20, 10], 12, 48
+        ], [
+            "2.2.3",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48, numZoomLevels: undefined},
+            [48, 24, 12], 12, 48
+        ], [
+            "2.2.4",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48, numZoomLevels: 3},
+            [48, 24, 12], 12, 48
+        ], [
+            "2.2.5",  {resolutions: [80, 40, 20, 10]}, {minResolution: 12, maxResolution: 48},
+            [48, 24, 12], 12, 48
+        ], [
+        /*
+         * Batch 2.3: maxResolution set in the layer options
+         */
+            "2.3.0",  {resolutions: [300, 150]}, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "2.3.1",  {numZoomLevels: 2}, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "2.3.2",  {maxResolution: 50}, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "2.3.3",  {scales: [4, 2, 1]}, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "2.3.4",  {minScale: 4}, {maxResolution: 4000, numZoomLevels: 3},
+            [4000, 2000, 1000], 1000, 4000
+        ], [
+            "2.3.5",  {resolutions: [300, 150]}, {maxResolution: 250},
+            [300, 150], 150, 250
+        ], [
+        /*
+         * Batch 2.4: minResolution set in the layer options
+         */
+            "2.4.0",  {resolutions: [300, 150]}, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "2.4.1",  {numZoomLevels: 2}, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "2.4.2",  {minResolution: 50}, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "2.4.3",  {scales: [4, 2, 1]}, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "2.4.4",  {maxScale: 1}, {minResolution: 40, numZoomLevels: 3},
+            [160, 80, 40], 40, 160
+        ], [
+            "2.4.5",  {resolutions: [300, 150]}, {minResolution: 250},
+            [300, 150], 250, 300
+        ], [
+        /*
+         * Batch 2.5: scales set in the layer options
+         */
+            "2.5.0",  {resolutions: [4, 2, 1]}, {scales: [400000, 200000, 100000]},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.5.1",  {numZoomLevels: 2}, {scales: [400000, 200000, 100000]},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.5.2",  {maxResolution: 4}, {scales: [400000, 200000, 100000]},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.5.3",  {minResolution: 1}, {scales: [400000, 200000, 100000]},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.5.4",  {units: "m"}, {scales: [400000, 200000, 100000]},
+            [141.11103491115225, 70.55551745557612, 35.27775872778806], 35.27775872778806, 141.11103491115225
+        ], [
+        /*
+         * Batch 2.6: minScale set in the layer options
+         */
+            "2.6.0",  {resolutions: [4, 2, 1]}, {minScale: 400000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.6.1",  {numZoomLevels: 2}, {minScale: 400000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.6.2",  {maxResolution: 4}, {minScale: 400000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.6.3", {scales: [400000, 200000, 100000]}, {minScale: 200000},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0006349563376084181
+        ], [
+        /*
+         * Batch 2.7: maxScale set in the layer options
+         */
+            "2.7.0",  {resolutions: [4, 2, 1]}, {maxScale: 100000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.7.1",  {numZoomLevels: 2}, {maxScale: 100000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.7.2",  {minResolution: 1}, {maxScale: 100000, numZoomLevels: 3},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.00031747816880420905, 0.0012699126752168362
+        ], [
+            "2.7.3", {scales: [400000, 200000, 100000]}, {maxScale: 200000},
+            [0.0012699126752168362, 0.0006349563376084181, 0.00031747816880420905], 0.0006349563376084181, 0.0012699126752168362
+        ], [
+        /*
+         * Batch 2.8: numZoomLevels set in the layer options
+         */
+            "2.8.0",  {maxResolution: 80}, {numZoomLevels: 4},
+            [80, 40, 20, 10], 10, 80
+        ], [
+            "2.8.1", {maxResolution: 80, numZoomLevels: 4}, {numZoomLevels: null},
+            [80, 40, 20, 10], 10, 80
+        ], [
+            "2.8.2", {maxResolution: 80, numZoomLevels: 4}, {numZoomLevels: undefined},
+            [80, 40, 20, 10], 10, 80
+        ]];
+
+        // run all cases (4 tests each)
+        var i, num = cases.length, c;
+        t.plan(num * 4);
+        for (i=0; i<num; ++i) {
+            c = cases[i];
+            initResolutionsTest(c[0], c[1], c[2], c[3], c[4], c[5]);
+        }
+
+    }
+
     function test_Layer_visibility(t) {
 
         t.plan(7);
@@ -469,9 +763,38 @@
         t.eq(hasBase, true, "when afterAdd is called, map has a base layer");
         
     }
+    
+    function test_setOpacity(t) {
+        t.plan(5);
 
+        var map, layer, log;
+        
+        map = new OpenLayers.Map("map");
+        layer = new OpenLayers.Layer("");
+        map.addLayer(layer);
 
+        log = [];
+        map.events.register('changelayer', t, function(event) {
+            log.push({layer: event.layer, property: event.property});
+        });
+        layer.setOpacity(0.42);
+        t.eq(layer.opacity, 0.42,
+             "setOpacity() set layer.opacity to correct value");
+        t.eq(log.length, 1,
+             "setOpacity() triggers changelayer once");
+        t.ok(log[0].layer == layer,
+             "changelayer listener called with expected layer");
+        t.eq(log[0].property, "opacity",
+             "changelayer listener called with expected property");
 
+        // This call must not trig the event because the opacity value is the same.
+        log = [];
+        layer.setOpacity(0.42);
+        t.eq(log.length, 0,
+             "setOpacity() does not trigger changelayer if the opacity value is the same");
+    }
+
+
 /******
  * 
  * 

Modified: sandbox/ahocevar/playground/tests/Map.html
===================================================================
--- sandbox/ahocevar/playground/tests/Map.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Map.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -33,6 +33,8 @@
         t.ok( map.events instanceof OpenLayers.Events, "map.events is an OpenLayers.Events" );
         t.ok( map.getMaxExtent() instanceof OpenLayers.Bounds, "map.maxExtent is an OpenLayers.Bounds" );
         t.ok( map.getNumZoomLevels() > 0, "map has a default numZoomLevels" );
+
+        map.destroy();
     }
     
     function test_Map_constructor_late_rendering(t) {
@@ -56,6 +58,9 @@
         
         t.ok(map.div == mapDiv, "Map is now rendered to the 'map' div.")
         t.ok( OpenLayers.Element.hasClass(map.div, "olMap"), "Map div has olMap class");
+        
+        map.destroy();
+        
     }
     
     function test_Map_constructor_renderTo(t) {
@@ -71,6 +76,8 @@
         
         var mapDiv = document.getElementById("map");
         t.ok(map.div == mapDiv, "Map is rendered to the 'map' div.")
+        
+        map.destroy();
     }
 
     function test_Map_setOptions(t) {
@@ -81,10 +88,12 @@
         t.eq(map.theme, 'foo', "theme is correctly set by setOptions");
         t.ok(map.maxExtent.equals(new OpenLayers.Bounds(100, 200, 300, 400)), 
              "maxExtent is correct after calling setOptions");
+        
+        map.destroy();
     }
 
     function test_Map_add_layers(t) {
-        t.plan(6);
+        t.plan(8);
         map = new OpenLayers.Map('map');
         var layer1 = new OpenLayers.Layer.WMS("Layer 1", 
             "http://octo.metacarta.com/cgi-bin/mapserv?",
@@ -101,6 +110,20 @@
                 "layer1 zIndex is set" );
         t.eq( parseInt(layer2.div.style.zIndex), map.Z_INDEX_BASE['BaseLayer'] + 5, 
                 "layer2 zIndex is set" );
+
+        map.events.register('preaddlayer', this, function(evt) {
+            return !(evt.layer.name === 'donotadd');
+        });
+        var layer3 = new OpenLayers.Layer.WMS("donotadd",
+            "http://octo.metacarta.com/cgi-bin/mapserv?",
+            {map: "/mapdata/vmap_wms.map", layers: "basic"});
+        map.addLayers([layer3]);
+        t.eq(map.layers.length, 2, "layer is not added since preaddlayer returns false");
+        layer3.name = 'pleaseadd';
+        map.addLayers([layer3]);
+        t.eq(map.layers.length, 3, "layer is added since preaddlayer returns true");
+        
+        map.destroy();
     }
 
     function test_Map_options(t) {
@@ -109,6 +132,8 @@
         t.eq( map.numZoomLevels, 6, "map.numZoomLevels set correctly via options hashtable" );
         t.eq( map.maxResolution, 3.14159, "map.maxResolution set correctly via options hashtable" );
         t.eq( map.theme, 'foo', "map theme set correctly." );
+
+        map.destroy();
     }
     
     function test_eventListeners(t) {
@@ -168,6 +193,8 @@
 
         map.getCenter().lon = 10;
         t.ok( map.getCenter().equals(ll), "map.getCenter returns a clone of map.center");
+
+        map.destroy();
     }
 
     function test_Map_zoomend_event (t) {
@@ -185,6 +212,8 @@
         map.setCenter(new OpenLayers.LonLat(2, 1), 0);
         map.zoomIn();
         map.zoomOut();
+
+        map.destroy();
     }
 
     function test_Map_add_remove_popup (t) {
@@ -229,6 +258,8 @@
             }
         }
         t.ok(!found, "popup.div successfully removed from the map's viewPort");
+
+        map.destroy();
     }
 
     function test_Map_add_popup_exclusive(t) {
@@ -255,6 +286,8 @@
                                          new OpenLayers.Size(200,200));
         map.addPopup(popup, true);
         t.eq(map.popups.length, 1, "addPopup exclusive mode works");
+
+        map.destroy();
     }   
     
 
@@ -306,6 +339,8 @@
         t.ok( !map.isValidLonLat(null), "null lonlat is not valid" );
         t.ok( map.isValidLonLat(new OpenLayers.LonLat(33862, 717606)), "lonlat outside max extent is valid" );
         t.ok( !map.isValidLonLat(new OpenLayers.LonLat(10, 10)), "lonlat outside max extent is not valid" );
+
+        map.destroy();
     }
 
     function test_Map_getLayer(t) {
@@ -327,6 +362,8 @@
 
         var gotLayer = OpenLayers.Map.prototype.getLayer.apply(m, ["chicken"]);
         t.ok( gotLayer == null, "getLayer correctly returns null when layer not found");
+
+        map.destroy();
     }
 
     function test_Map_getLayersBy(t) {
@@ -625,6 +662,7 @@
         
         t.eq( map.layers.length, 1, "Map does not allow double adding of layers." );
     
+        map.destroy();
     }
 
     function test_Map_setBaseLayer(t) {
@@ -654,6 +692,8 @@
         
         map.setBaseLayer(wmslayer2);
         t.ok(map.baseLayer == wmslayer2, "setbaselayer correctly sets 'baseLayer' property");
+
+        map.destroy();
     }
     
     function test_Map_removeLayer(t) {
@@ -704,6 +744,8 @@
         map.removeLayer(layer0);
         t.eq(map.getResolution(), layer0.resolutions[1],
              "correct resolution after removal");
+
+        map.destroy();
     }
 
     function test_Map_removeLayer_zindex(t) {
@@ -722,6 +764,8 @@
              "correct z-index after removeLayer");
         t.eq(parseInt(layer2.div.style.zIndex), map.Z_INDEX_BASE['Overlay'] + 5,
              "correct z-index after removeLayer");
+
+        map.destroy();
     }
 
     function test_Map_setBaseLayer_after_pan (t) {
@@ -741,6 +785,8 @@
         map.pan(0, -200, {animate:false});
         map.setBaseLayer(wmsLayer);
         t.eq(map.layerContainerDiv.style.top, "0px", "layerContainer is recentered after setBaseLayer");
+        
+        map.destroy();
     }
 
     function test_Map_moveLayer (t) {
@@ -781,6 +827,8 @@
             "layer div has the right zIndex after moving up" );
         t.eq( map.getLayerIndex(wmslayer3), 0, "top layer is now on the bottom" );
         t.eq( ct, 3, "raiseLayer triggered changelayer the right # of times" );
+
+        map.destroy();
     }
 
     function test_Map_moveTo(t) {
@@ -803,6 +851,8 @@
         var ll = new OpenLayers.LonLat(-100,-150);
         map.moveTo(ll, 2);
         t.ok(map.getCenter().equals(new OpenLayers.LonLat(0,0)), "safely sets out-of-bounds lonlat");
+
+        map.destroy();
     }
 
     function test_Map_defaultTheme(t) {
@@ -827,6 +877,8 @@
         map = new OpenLayers.Map('map');
         t.eq(links.length, document.getElementsByTagName('link').length,
              "calling the map constructor twice with the same theme doesn't add duplicate link nodes");
+
+        map.destroy();
     }
 
     function test_Map_customTheme(t) {
@@ -851,6 +903,8 @@
         t.ok(themeNode != null, "a link node with the theme href was added");
         t.eq(themeNode.rel, "stylesheet", "node added has rel set to stylesheet");
         t.eq(themeNode.type, "text/css", "node added has type set to text/css");
+        
+        map.destroy();
     }
 
     function test_Map_noTheme(t) {
@@ -863,8 +917,39 @@
         map = new OpenLayers.Map('map', options);
 
         t.eq(nodeCount, head.childNodes.length, "with no theme, a node is not added to document head" );
+
+        map.destroy();
     }
 
+    function test_Map_addControls(t) {
+        t.plan(5);
+        var map = new OpenLayers.Map('map', {
+            controls: []
+        });
+        var controls = [
+          new OpenLayers.Control({id:'firstctrl'}),
+          new OpenLayers.Control({id:'secondctrl'})
+        ];
+        map.addControls(controls);
+        t.eq(map.controls.length, 2, "two controls were added by map.addControls without a px-array");
+        t.eq(map.controls[0].id, 'firstctrl', "control with index 0 has id 'firstctrl'");
+        t.eq(map.controls[1].id, 'secondctrl', "control with index 1 has id 'secondctrl'");
+        
+        var controls2 = [
+          new OpenLayers.Control({id:'thirdctrl'}),
+          new OpenLayers.Control({id:'fourthctrl'}),
+          new OpenLayers.Control({id:'fifthctrl'})
+        ];
+        // this array is intentionally one element shorter than the above       
+        var pixels2 = [
+          null,
+          new OpenLayers.Pixel(27,11)
+        ];
+        map.addControls(controls2, pixels2);
+        t.eq(map.controls.length, 5, "three additional controls were added by map.addControls with a px-array");
+        t.eq(map.controls[3].position.toString(), pixels2[1].toString(), "control 'fourthctrl' has position set to given px");
+    }
+
     function test_Map_getControl(t) {
         t.plan(2);
         
@@ -878,6 +963,8 @@
         
         gotControl = map1.getControl("bogus id");
         t.ok(gotControl == null, "getControl() for bad id returns null");
+
+        map1.destroy();
     }
 
     function test_Map_removeControl(t) {
@@ -926,6 +1013,9 @@
         map1.removeControl(control);
         newNumControls = map1.controls.length;
         t.ok( newNumControls == oldNumControls, "removing bad controlid doesnt crash or decrease control count")
+
+        map1.destroy();
+
     }
 
     function test_Map_restrictedExtent(t) {
@@ -1022,6 +1112,8 @@
         t.eq(map.getExtent().getCenterLonLat().toString(),
              se.toString(),
              "map extent not restricted with null restrictedExtent for se");
+
+        map.destroy();
     }
     
     function test_Map_getResolutionForZoom(t) {
@@ -1040,6 +1132,46 @@
         map.destroy();
     }
     
+    function test_zoomTo(t) {
+        t.plan(8);
+        
+        var map = new OpenLayers.Map("map");
+        map.addLayer(new OpenLayers.Layer(null, {
+            isBaseLayer: true
+        }));
+        
+        map.zoomToMaxExtent();
+        
+        map.zoomTo(2);
+        t.eq(map.getZoom(), 2, 'zoomTo(2)');
+
+        map.zoomTo(3.6);
+        t.eq(map.getZoom(), 4, 'zoomTo(3.6)');
+        
+        map.zoomTo("4.6");
+        t.eq(map.getZoom(), 5, 'zoomTo("4.6")');
+        
+        map.zoomTo("1.2");
+        t.eq(map.getZoom(), 1, 'zoomTo("1.2")');
+        
+        // now allow fractional zoom
+        map.fractionalZoom = true;
+        
+        map.zoomTo(2);
+        t.eq(map.getZoom(), 2, '[fractionalZoom] zoomTo(2)');
+
+        map.zoomTo(3.6);
+        t.eq(map.getZoom(), 3.6, '[fractionalZoom] zoomTo(3.6)');
+        
+        map.zoomTo("4.6");
+        t.eq(map.getZoom(), 4.6, '[fractionalZoom] zoomTo("4.6")');
+        
+        map.zoomTo("1.2");
+        t.eq(map.getZoom(), 1.2, '[fractionalZoom] zoomTo("1.2")');
+        
+        map.destroy();
+    }
+    
     function test_Map_getUnits(t) {
         t.plan(2);
         var map = new OpenLayers.Map("map");
@@ -1212,7 +1344,7 @@
     
     function test_allOverlays(t) {
         
-        t.plan(16);
+        t.plan(18);
 
         var map = new OpenLayers.Map({
             div: "map", allOverlays: true
@@ -1296,11 +1428,200 @@
        
         map.destroy();
         
+        // make sure setVisibility is called when adding a single layer to the map
+        map = new OpenLayers.Map({
+            div: "map", allOverlays: true
+        });
+        var count = 0;
+        var layer = new OpenLayers.Layer(null, {
+            visibility: true,
+            maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
+            setVisibility: function() {
+                ++count;
+                OpenLayers.Layer.prototype.setVisibility.apply(this, arguments);
+            }
+        });
+        map.addLayer(layer);
+        map.zoomToMaxExtent();
+        
+        t.eq(count, 1, "setVisibility called when visibility is true in layer config");
+        t.eq(layer.div.style.display, "", "layer is visible.");
+
+        map.destroy();
+        
     }
+    
+    function test_panTo(t) {
+        
+        t.plan(2);
+        
+        var map = new OpenLayers.Map("map");
+        map.addLayer(
+            new OpenLayers.Layer(null, {isBaseLayer: true})
+        );
+        map.setCenter(new OpenLayers.LonLat(0, 0), 0);
+        
+        map.panTo(new OpenLayers.LonLat(1, 0));
+        t.eq(map.panTween.playing, true, "the map pan tween is playing before destroy");
+        
+        map.destroy();
+        t.ok(!map.panTween || !map.panTween.playing, "the map pan tween is not playing after destroy");
+    }
 
+    function test_updateSize(t) {
+        t.plan(2);
+
+        var map, moveToCnt, size;
+
+        map = new OpenLayers.Map({div: "map"});
+        map.addLayer(new OpenLayers.Layer("layer", {isBaseLayer: true}));
+
+        map.moveTo = function() {
+            moveToCnt++;
+            OpenLayers.Map.prototype.moveTo.apply(this, arguments);
+        };
+
+        map.getCurrentSize = function() {
+            return size;
+        };
+
+        // map has no center
+        // 1 test
+        moveToCnt = 0;
+        size = new OpenLayers.Size(650, 350);
+        map.updateSize();
+        t.eq(moveToCnt, 0, "updateSize doesn't move the map if it doesn't have a center");
+
+        // map has a center
+        // 1 test
+        map.zoomToMaxExtent();
+        moveToCnt = 0;
+        size = new OpenLayers.Size(600, 300);
+        map.updateSize();
+        t.eq(moveToCnt, 1, "updateSize move the map if it has a center");
+
+        map.destroy();
+    }
+    
+    function test_invisible_map(t) {
+        /** 
+         * This test confirms that initializing a map using an element that is 
+         * not currently displayed doesn't cause any trouble.
+         */
+        t.plan(1);
+        
+        var map, msg = "initializing a map on an undisplayed element";
+        try {
+            map = new OpenLayers.Map("invisimap");
+        } catch (err) {
+            msg += ": " + err;
+        }
+        t.ok(!!map, msg);
+        
+        if (map) {
+            map.destroy();
+        }        
+    }
+    
+    function test_layers_option(t) {
+        
+        t.plan(3);
+
+        var map = new OpenLayers.Map({
+            div: "map",
+            layers: [
+                new OpenLayers.Layer()
+            ]
+        });
+        
+        t.eq(map.layers.length, 1, "single layer from options added");
+
+        map.destroy();
+        
+        map = new OpenLayers.Map({
+            div: "map",
+            layers: [
+                new OpenLayers.Layer(null, {isBaseLayer: true}),
+                new OpenLayers.Layer(null, {isBaseLayer: false})
+            ]
+        });
+        
+        t.eq(map.layers.length, 2, "multiple layers added from options");
+        t.ok(map.baseLayer, "map has a base layer");
+        
+    }
+    
+    function test_center_option(t) {
+        t.plan(6);
+        
+        var map, msg;
+        
+        
+        // try setting center without layers, this has no effect
+        var failed = false;
+        try {
+            map = new OpenLayers.Map({
+                div: "map",
+                center: new OpenLayers.LonLat(1, 2)
+            });
+            msg = "center option without layers has no effect";
+        } catch (err) {
+            failed = true;
+            msg = "center option without layers throws error";
+        }
+        t.ok(!failed, msg);
+        
+        if (map) {
+            map.destroy();
+        }
+        
+        
+        // set center without zoom
+        var center = new OpenLayers.LonLat(1, 2);
+        map = new OpenLayers.Map({
+            div: "map",
+            layers: [new OpenLayers.Layer(null, {isBaseLayer: true})],
+            center: center
+        });
+        
+        t.ok(center.equals(map.getCenter()), "map center set without zoom");
+        
+        map.destroy();
+        
+        // set center and zoom
+        var zoom = 3;
+        map = new OpenLayers.Map({
+            div: "map",
+            layers: [new OpenLayers.Layer(null, {isBaseLayer: true})],
+            center: center,
+            zoom: zoom
+        });
+
+        t.ok(center.equals(map.getCenter()), "map center set with center and zoom");
+        t.eq(zoom, map.getZoom(), "map zoom set with center and zoom");
+        
+        map.destroy();
+        
+        // set center and zoom with all overlays
+        map = new OpenLayers.Map({
+            div: "map",
+            allOverlays: true,
+            layers: [new OpenLayers.Layer()],
+            center: center,
+            zoom: zoom
+        });
+        
+        t.ok(center.equals(map.getCenter()), "map center set with all overlays");
+        t.eq(zoom, map.getZoom(), "map zoom set with all overlays");        
+        
+        map.destroy();
+        
+    }
+
   </script>
 </head>
 <body>
     <div id="map" style="width: 600px; height: 300px;"/>
+    <div style="display: none;"><div id="invisimap"></div></div>
 </body>
 </html>

Modified: sandbox/ahocevar/playground/tests/Marker/Box.html
===================================================================
--- sandbox/ahocevar/playground/tests/Marker/Box.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Marker/Box.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -26,7 +26,7 @@
         t.ok( box.bounds.equals(bounds), "bounds object correctly set");
         t.ok( box.div != null, "div created");
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq( box.div.style[prop], "hidden", "div style overflow hidden");
         t.ok( box.events != null, "events object created");
         t.eq( g_Color, borderColor, "setBorder called with correct border color");        

Copied: sandbox/ahocevar/playground/tests/OpenLayers1.html (from rev 10919, trunk/openlayers/tests/OpenLayers1.html)
===================================================================
--- sandbox/ahocevar/playground/tests/OpenLayers1.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/OpenLayers1.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,16 @@
+<html>
+<head>
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        function test_OpenLayers(t) {
+            t.plan(1);
+
+            var script = document.getElementById("script");
+
+            t.eq(OpenLayers._getScriptLocation(), "../", "Script location correctly detected.");
+        }
+    </script>
+</head>
+<body>
+</body>
+</html>

Copied: sandbox/ahocevar/playground/tests/OpenLayers2.html (from rev 10919, trunk/openlayers/tests/OpenLayers2.html)
===================================================================
--- sandbox/ahocevar/playground/tests/OpenLayers2.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/OpenLayers2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+<html>
+<head>
+    <script src="bogus/1/OpenLayers.js-foo"></script>
+    <script src="bogus/2/foo-OpenLayers.js"></script>
+    <script src="../lib/OpenLayers.js?foo"></script>
+    <script src="bogus/3/after-OpenLayers.js"></script>
+    <script type="text/javascript">
+        function test_OpenLayers(t) {
+            t.plan(1);
+
+            var script = document.getElementById("script");
+
+            t.eq(OpenLayers._getScriptLocation(), "../", "Script location with search string correctly detected, and not fooled by other scripts.");
+        }
+    </script>
+</head>
+<body>
+</body>
+</html>

Copied: sandbox/ahocevar/playground/tests/OpenLayers3.html (from rev 10919, trunk/openlayers/tests/OpenLayers3.html)
===================================================================
--- sandbox/ahocevar/playground/tests/OpenLayers3.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/OpenLayers3.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,19 @@
+<html>
+<head>
+    <script>
+    var OpenLayers = {singleFile: true};
+    </script>
+    <script src="../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        function test_OpenLayers(t) {
+            t.plan(1);
+
+            var script = document.getElementById("script");
+
+            t.eq(OpenLayers._getScriptLocation(), "../lib/", "Script location for single file build correctly detected.");
+        }
+    </script>
+</head>
+<body>
+</body>
+</html>

Copied: sandbox/ahocevar/playground/tests/OpenLayers4.html (from rev 10919, trunk/openlayers/tests/OpenLayers4.html)
===================================================================
--- sandbox/ahocevar/playground/tests/OpenLayers4.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/OpenLayers4.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,18 @@
+<html>
+<head>
+    <script type="text/javascript">
+	OpenLayers = {singleFile: true}; // just to make the test run faster
+        document.write('<scr'+'ipt src="../lib/OpenLayers.js"></scr'+'ipt>');
+        document.write('<scr'+'ipt src="bogus/foo-/OpenLayers.js"></scr'+'ipt>');
+    </script>
+    <script type="text/javascript">
+        function test_OpenLayers(t) {
+            t.plan(1);
+            t.eq(OpenLayers._getScriptLocation(), "../lib/",
+                 "Script location correctly detected, and not fooled by other scripts.");
+        }
+    </script>
+</head>
+<body>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Popup/Anchored.html
===================================================================
--- sandbox/ahocevar/playground/tests/Popup/Anchored.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Popup/Anchored.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -11,7 +11,7 @@
         popup = new OpenLayers.Popup.Anchored();
 
         t.ok( popup instanceof OpenLayers.Popup.Anchored, "new OpenLayers.Popup.Anchored returns Popup.Anchored object" );
-        t.ok(popup.id.startsWith("OpenLayers.Popup.Anchored"), "valid default popupid");
+        t.ok(OpenLayers.String.startsWith(popup.id, "OpenLayers.Popup.Anchored"), "valid default popupid");
         var firstID = popup.id;
         t.eq(popup.contentHTML, null, "good default popup.contentHTML");
 

Modified: sandbox/ahocevar/playground/tests/Popup.html
===================================================================
--- sandbox/ahocevar/playground/tests/Popup.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Popup.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -88,8 +88,8 @@
     }
     function test_Popup_keepInMap(t) {
         
-        var gb = OpenLayers.Util.getBrowserName;
-        OpenLayers.Util.getBrowserName = function() { return "mock"; }
+        var bn = OpenLayers.BROWSER_NAME;
+        OpenLayers.BROWSER_NAME = "mock";
         t.plan(3);
         var map = new OpenLayers.Map("map");
         map.addLayer(new OpenLayers.Layer("", {isBaseLayer: true}));
@@ -120,7 +120,7 @@
         t.ok(safeSizePan.equals(safeSizePanKeep), "Panning means that all sizes are equal");
         t.ok(safeSize.w < safeSizePan.w, "Width of non-panning is less");    
         t.ok(safeSize.h < safeSizePan.h, "Height of non-panning is less");    
-        OpenLayers.Util.getBrowserName = gb; 
+        OpenLayers.BROWSER_NAME = bn;
     }    
     function test_Popup_draw(t) {
         t.plan( 15 );
@@ -155,7 +155,7 @@
         t.eq(contentDiv.id, "chicken_contentDiv", "correct content div id");
         t.eq(contentDiv.style.position, "relative", "correct content div position");
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq(contentDiv.style[prop], "", "correct content div overflow");
         t.eq(contentDiv.innerHTML, content, "correct content div content");
 
@@ -169,7 +169,7 @@
             t.eq(popup.div.style.filter, "alpha(opacity=" + opacity*100 + ")", "good default popup.opacity");
         }
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(popup.div.style.borderTopWidth == s[0] && popup.div.style.borderTopStyle == s[1], "good default popup.border")
         } else {

Modified: sandbox/ahocevar/playground/tests/Projection.html
===================================================================
--- sandbox/ahocevar/playground/tests/Projection.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Projection.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -21,7 +21,47 @@
 
          t.eq(projection.equals(null), false, "equals on null projection returns false");
          t.eq(projection.equals({}), false, "equals on null projection object returns false (doesn't call getCode)");
-     } 
+     }
+     
+     function test_Projection_equals(t) {
+         t.plan(8);
+         var origTransforms = OpenLayers.Util.extend({}, OpenLayers.Projection.transforms);
+         OpenLayers.Projection.addTransform("EPSG:4326", "FOO", OpenLayers.Projection.nullTransform);
+         OpenLayers.Projection.addTransform("FOO", "EPSG:4326", OpenLayers.Projection.nullTransform);
+         var projection = new OpenLayers.Projection("FOO");
+         t.eq(projection.equals(new OpenLayers.Projection("EPSG:4326")), true, "EPSG:4326 and FOO are equal without proj4js");
+         t.eq(projection.equals(new OpenLayers.Projection("EPSG:900913")), false, "EPSG:900913 and FOO are not equal without proj4js");
+         t.eq(new OpenLayers.Projection("EPSG:4326").equals(new OpenLayers.Projection("EPSG:4326")), true, "EPSG:4326 and EPSG:4326 are equal without proj4js");
+         t.eq(new OpenLayers.Projection("BAR").equals(new OpenLayers.Projection("EPSG:4326")), false, "Projection.equals() returns false for unknown projections withoug proj4js");
+         OpenLayers.Projection.transforms = origTransforms;
+         
+         var proj1 = new OpenLayers.Projection("EPSG:4326");
+         var proj2 = new OpenLayers.Projection("FOO");
+         var proj3 = new OpenLayers.Projection("EPSG:900913");
+         var proj4 = new OpenLayers.Projection("EPSG:4326");
+         var proj5 = new OpenLayers.Projection("BAR");
+
+         // conditionally mock up proj4js
+         var hasProj = !!window.Proj4js;
+         if (!hasProj) {
+             window.Proj4js = true;
+         }
+         proj1.proj = {defData: "+title= WGS84 +foo=bar +x=0"};
+         proj2.proj = {defData: "+title=FOO +foo=bar +x=0", srsCode: "FOO"};
+         proj3.proj = {defData: "+title=Web Mercator +foo=bar +x=0 +I=am-different"};
+         proj4.proj = proj1.proj;
+         proj5.proj = {srsCode: "BAR"};
+
+         t.eq(proj2.equals(proj1), true, "EPSG:4326 and FOO are equal with proj4js");
+         t.eq(proj2.equals(proj3), false, "EPSG:900913 and FOO are not equal with proj4js");
+         t.eq(proj1.equals(proj4), true, "EPSG:4326 and EPSG:4326 are equal with proj4js");
+         t.eq(proj2.equals(proj5), false, "Projection.equals() returns false for unknown projections with proj4js");
+         
+         if (!hasProj) {
+             delete window.Proj4js
+         }
+         
+     }
        
     </script> 
   </head> 

Modified: sandbox/ahocevar/playground/tests/Protocol/HTTP.html
===================================================================
--- sandbox/ahocevar/playground/tests/Protocol/HTTP.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Protocol/HTTP.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -273,6 +273,291 @@
         t.eq(ret, null, 'parseFeatures returns expected value');
     }
 
+    function test_filterToParams(t) {
+        t.plan(30);
+
+        // setup
+
+        var protocol, filter, params;
+
+        protocol = new OpenLayers.Protocol.HTTP();
+
+        // 1 test
+        var filter = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.BBOX,
+            value: new OpenLayers.Bounds(0, 1, 2, 3)
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.bbox, [0, 1, 2, 3],
+             "filterToParams sets correct bbox param if passed a BBOX filter");
+
+        // 3 tests
+        var lon = 100, lat = 200, tolerance = 10;
+        filter = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.DWITHIN,
+            value: new OpenLayers.Geometry.Point(lon, lat),
+            distance: tolerance
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.lon, lon,
+             "filterToParams sets correct lon param if passed a DWITHIN filter");
+        t.eq(params.lat, lat,
+             "filterToParams sets correct lat param if passed a DWITHIN filter");
+        t.eq(params.tolerance, tolerance,
+             "filterToParams sets correct tolerance param if passed a DWITHIN filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.WITHIN,
+            value: new OpenLayers.Geometry.Point(lon, lat)
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.lon, lon,
+             "filterToParams sets correct lon param if passed a WITHIN filter");
+        t.eq(params.lat, lat,
+             "filterToParams sets correct lat param if passed a WITHIN filter");
+
+        // Some bbox filters used in the next tests.
+
+        var bboxFilter1 = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.BBOX,
+            value:  new OpenLayers.Bounds(0, 0, 10, 10)
+        });
+
+        var bboxFilter2 = new OpenLayers.Filter.Spatial({
+            type: OpenLayers.Filter.Spatial.BBOX,
+            value:  new OpenLayers.Bounds(0, 0, 20, 20)
+        });
+
+        // 1 test
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: []
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params, {},
+             "filterToParams returns empty object if given empty AND Logical filter");
+
+        // 1 test
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.OR,
+            filters: [
+                bboxFilter1
+            ]
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params, {},
+             "filterToParams does not support OR Logical filter");
+
+        // 1 test
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: [
+                bboxFilter1
+            ]
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.bbox, [0, 0, 10, 10],
+             "filterToParams sets correct bbox param if passed " +
+             "a Logical filter containing a BBOX");
+
+        // 1 test
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: [
+                bboxFilter1, bboxFilter2
+            ]
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.bbox, [0, 0, 20, 20],
+             "filterToParams sets correct bbox param if passed " +
+             "multiple BBOX filter in a Logical filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.EQUAL_TO,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an EQUAL_TO filter");
+        t.eq(params["foo__eq"], "bar",
+             "filterToParams sets correct param key and value if passed an EQUAL_TO filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an NOT_EQUAL_TO filter");
+        t.eq(params["foo__ne"], "bar",
+             "filterToParams sets correct param key and value if passed an NOT_EQUAL_TO filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LESS_THAN,
+            property: "foo",
+            value: "bar"
+        });
+        var params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an LESS_THAN filter");
+        t.eq(params["foo__lt"], "bar",
+             "filterToParams sets correct param key and value if passed an LESS_THAN filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,
+            property: "foo",
+            value: "bar"
+        });
+        var params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an LESS_THAN_OR_EQUAL_TO filter");
+        t.eq(params["foo__lte"], "bar",
+             "filterToParams sets correct param key and value if passed an LESS_THAN_OR_EQUAL_TO filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.GREATER_THAN,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an GREATER_THAN filter");
+        t.eq(params["foo__gt"], "bar",
+             "filterToParams sets correct param key and value if passed an GREATER_THAN filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an GREATER_THAN_OR_EQUAL_TO filter");
+        t.eq(params["foo__gte"], "bar",
+             "filterToParams sets correct param key and value if passed an GREATER_THAN_OR_EQUAL_TO filter");
+
+        // 2 tests
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LIKE,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed a LIKE filter");
+        t.eq(params["foo__ilike"], "bar",
+             "filterToParams sets correct param key and value if passed an LIKE filter");
+
+        // 4 tests
+        filter = new OpenLayers.Filter.Logical({
+            type: OpenLayers.Filter.Logical.AND,
+            filters: [
+                new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                    property: "foo",
+                    value: "bar"
+                }),
+                new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.LESS_THAN,
+                    property: "foo2",
+                    value: "baz"
+                })
+            ]
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed an EQUAL_TO filter within a AND filter");
+        t.eq(params["foo__eq"], "bar",
+             "filterToParams sets correct param key and value if passed an EQUAL_TO filter within a AND filter");
+        t.eq(params.queryable[1], "foo2",
+             "filterToParams sets correct queryable param if passed a LESS_THAN filter within a AND filter");
+        t.eq(params["foo2__lt"], "baz",
+             "filterToParams sets correct param key and value if passed a LESS_THAN filter within a AND filter");
+
+        // 2 tests
+        protocol = new OpenLayers.Protocol.HTTP({wildcarded: true});
+        filter = new OpenLayers.Filter.Comparison({
+            type: OpenLayers.Filter.Comparison.LIKE,
+            property: "foo",
+            value: "bar"
+        });
+        params = protocol.filterToParams(filter);
+        t.eq(params.queryable[0], "foo",
+             "filterToParams sets correct queryable param if passed a LIKE filter (wildcarded true)");
+        t.eq(params["foo__ilike"], "%bar%",
+             "filterToParams sets correct param key and value if passed an LIKE filter (wildcarded true)");
+    }
+
+    function test_regex2value(t) {
+        t.plan(16);
+
+        // setup
+
+        var protocol = new OpenLayers.Protocol.HTTP();
+        var value;
+
+        // test
+
+        value = protocol.regex2value("foo");
+        t.eq(value, "foo", 'regex2value converts "foo" to "foo"');
+
+        value = protocol.regex2value("foo%");
+        t.eq(value, "foo\\%", 'regex2value converts "foo%" to "foo\\%"');
+
+        value = protocol.regex2value("foo.*");
+        t.eq(value, "foo%", 'regex2value converts "foo.*" to "foo%"');
+
+        value = protocol.regex2value("f.*oo.*");
+        t.eq(value, "f%oo%", 'regex2value converts "f.*oo.*" to "f%oo%"');
+
+        value = protocol.regex2value("foo.");
+        t.eq(value, "foo_", 'regex2value converts "foo." to "foo_"');
+
+        value = protocol.regex2value("f.oo.");
+        t.eq(value, "f_oo_", 'regex2value converts "f.oo." to "f_oo_"');
+
+        value = protocol.regex2value("f.oo.*");
+        t.eq(value, "f_oo%", 'regex2value converts "f.oo.*" to "f_oo%"');
+
+        value = protocol.regex2value("foo\\\\");
+        t.eq(value, "foo\\\\", 'regex2value converts "foo\\\\" to "foo\\\\"');
+
+        value = protocol.regex2value("foo\\.");
+        t.eq(value, "foo.", 'regex2value converts "foo\\." to "foo."');
+
+        value = protocol.regex2value("foo\\\\.");
+        t.eq(value, "foo\\\\_", 'regex2value converts "foo\\\\." to "foo\\\\_"');
+
+        value = protocol.regex2value("foo\\*");
+        t.eq(value, "foo*", 'regex2value converts "foo\\*" to "foo*"');
+
+        value = protocol.regex2value("foo\\\\*");
+        t.eq(value, "foo\\\\*", 'regex2value converts "foo\\\\*" to "foo\\\\*"');
+
+        value = protocol.regex2value("foo\\\\.*");
+        t.eq(value, "foo\\\\%", 'regex2value converts "foo\\\\.*" to "foo\\\\%"');
+
+        value = protocol.regex2value("fo\\.o.*");
+        t.eq(value, "fo.o%", 'regex2value converts from "fo\\.o.*" to "fo.o%"');
+
+        value = protocol.regex2value("fo.*o\\.");
+        t.eq(value, "fo%o.", 'regex2value converts from "fo.*o\\." to "to%o."');
+
+        value = protocol.regex2value("\\*\\..*.\\\\.*\\\\.%");
+        t.eq(value, "*.%_\\\\%\\\\_\\%",
+             'regex2value converts from "\\*\\..*.\\\\.*\\\\.%" ' +
+             'to "*.%_\\\\%\\\\_\\%"');
+   }
+
     function test_create(t) {
         t.plan(10);
         var protocol = new OpenLayers.Protocol.HTTP({
@@ -411,6 +696,34 @@
         OpenLayers.Request.PUT = _put;
     }
 
+    function test_update_featureurl(t) {
+
+        // test that OpenLayers.Request.PUT receives the URL
+        // set in the feature
+        // http://trac.openlayers.org/ticket/2393#comment:11
+
+        t.plan(1);
+
+        var protocol = new OpenLayers.Protocol.HTTP({
+            'url': 'foo_url',
+            'format': {'write': function() {}}
+        });
+
+        // feature to pass to update
+        var feature = {'feature':'feature', 'url': 'bar_url'};
+
+        var _put = OpenLayers.Request.PUT;
+
+        OpenLayers.Request.PUT = function(options) {
+            t.eq(options.url, feature.url,
+                'PUT called with correct url in options');
+        };
+
+        protocol.update(feature);
+
+        OpenLayers.Request.PUT = _put;
+    }
+
     function test_handleResponse(t) {
         t.plan(6);
 
@@ -532,6 +845,34 @@
         OpenLayers.Request.DELETE = _delete;
     }
 
+    function test_delete_featureurl(t) {
+
+        // test that OpenLayers.Request.DELETE receives the URL
+        // set in the feature
+        // http://trac.openlayers.org/ticket/2393#comment:11
+
+        t.plan(1);
+
+        var protocol = new OpenLayers.Protocol.HTTP({
+            'url': 'foo_url',
+            'format': {'write': function() {}}
+        });
+
+        // feature to pass to update
+        var feature = {'feature':'feature', 'url': 'bar_url'};
+
+        var _delete = OpenLayers.Request.DELETE;
+
+        OpenLayers.Request.DELETE = function(options) {
+            t.eq(options.url, feature.url,
+                'DELETE called with correct url in options');
+        };
+
+        protocol['delete'](feature);
+
+        OpenLayers.Request.DELETE = _delete;
+    }
+
     function test_handleDelete(t) {
         t.plan(4);
 
@@ -709,7 +1050,7 @@
         });        
         protocol.read();
         
-        t.delay_call(0.5, function() {
+        t.delay_call(1, function() {
             t.eq(log1.callbackCalled, true, "[read] callback called");
             t.eq(log1.callbackScope, scope, "[read] correct scope");
             t.ok(log1.request instanceof OpenLayers.Request.XMLHttpRequest, "[read] correct priv type");
@@ -731,7 +1072,7 @@
             {state: OpenLayers.State.DELETE, url: "./3"},
             {state: OpenLayers.State.DELETE, url: "./4"}
         ]);
-        t.delay_call(0.5, function() {
+        t.delay_call(1, function() {
             t.eq(log2.called, 1, "[commit] Callback called once.");
             t.eq(log2.scope, scope, "[commit] Correct scope.");
         });

Copied: sandbox/ahocevar/playground/tests/Protocol/SOS.html (from rev 10919, trunk/openlayers/tests/Protocol/SOS.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Protocol/SOS.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Protocol/SOS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,57 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+
+    function test_constructor(t) {
+        t.plan(4);
+        var a = new OpenLayers.Protocol.SOS({
+            url: "foo",
+            fois: ["a", "b", "c"]
+        });
+
+        t.eq(a.url, "foo", "constructor sets url");
+        t.eq(a.options.url, a.url, "constructor copies url to options.url");
+        t.eq(a.fois[0], "a", "constructor sets the fois correctly");
+        t.eq((a.format instanceof OpenLayers.Format.SOSGetFeatureOfInterest), true, "Constructor sets format correctly"); 
+    }
+
+    function test_read(t) {
+        t.plan(4);
+
+        var protocol = new OpenLayers.Protocol.SOS({
+            url: "http://some.url.org/sos?",
+            fois: ["foi1", "foi2"],
+            parseFeatures: function(request) {
+                t.eq(request.responseText, "foo", "parseFeatures called properly");
+                return "foo";
+            }
+        });
+
+        var _POST = OpenLayers.Request.POST;
+
+        var expected, status;
+        OpenLayers.Request.POST = function(obj) {
+            t.xml_eq(new OpenLayers.Format.XML().read(obj.data).documentElement, expected, "GetFeatureOfInterest request is correct");
+            obj.status = status;
+            obj.responseText = "foo";
+            obj.options = {};
+            t.delay_call(0.1, function() {obj.callback.call(this)});
+            return obj;
+        };
+
+        var xml = '<GetFeatureOfInterest xmlns="http://www.opengis.net/sos/1.0" version="1.0.0" service="SOS" xsi:schemaLocation="http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><FeatureOfInterestId>foi1</FeatureOfInterestId><FeatureOfInterestId>foi2</FeatureOfInterestId></GetFeatureOfInterest>';
+        expected = new OpenLayers.Format.XML().read(xml).documentElement;
+        status = 200;
+        var response = protocol.read({callback: function(response) {
+            t.eq(response.features, "foo", "user callback properly called with features");
+            t.eq(response.code, OpenLayers.Protocol.Response.SUCCESS, "success reported properly");
+        }});
+
+    }
+
+  </script>
+</head>
+<body>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Protocol/WFS.html
===================================================================
--- sandbox/ahocevar/playground/tests/Protocol/WFS.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Protocol/WFS.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -23,7 +23,7 @@
         t.ok(protocol instanceof OpenLayers.Protocol.WFS.v1_1_0,
              "initialize returns instance of custom versioned protocol")
     }
-    
+
     function test_read(t) {
         t.plan(6);
 
@@ -31,14 +31,14 @@
             url: "http://some.url.org",
             featureNS: "http://namespace.org",
             featureType: "type",
-            parseFeatures: function(request) {
-                t.eq(request.responseText, "foo", "parseFeatures called properly");
+            parseResponse: function(request) {
+                t.eq(request.responseText, "foo", "parseResponse called properly");
                 return "foo";
             }
         });
 
         var _POST = OpenLayers.Request.POST;
-        
+
         var expected, status;
         OpenLayers.Request.POST = function(obj) {
             t.xml_eq(new OpenLayers.Format.XML().read(obj.data).documentElement, expected, "GetFeature request is correct");
@@ -48,14 +48,14 @@
             t.delay_call(0.1, function() {obj.callback.call(this)});
             return obj;
         };
-        
+
         expected = readXML("GetFeature_1");
         status = 200;
         var response = protocol.read({callback: function(response) {
             t.eq(response.features, "foo", "user callback properly called with features");
             t.eq(response.code, OpenLayers.Protocol.Response.SUCCESS, "success reported properly");
         }});
-        
+
         options = {
             maxFeatures: 10,
             featureType: 'type2',
@@ -71,7 +71,7 @@
 
         OpenLayers.Request.POST = _POST;
     }
-        
+
     function test_commit(t){
         t.plan(4);
 
@@ -90,8 +90,8 @@
         };
 
         var _POST = OpenLayers.Request.POST;
-        
-        var expected;        
+
+        var expected;
         OpenLayers.Request.POST = function(obj) {
             t.xml_eq(new OpenLayers.Format.XML().read(obj.data).documentElement, expected, "Transaction XML with Insert, Update and Delete created correctly");
             obj.responseText = "foo";
@@ -99,7 +99,7 @@
             t.delay_call(0.1, function() {obj.callback.call(this)});
             return obj;
         };
-        
+
         var featureDelete = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(42, 7), {has : "cheeseburger"});
         featureDelete.fid = "fid.37";
         featureDelete.state = OpenLayers.State.DELETE;
@@ -124,7 +124,7 @@
                 t.eq(response.code, OpenLayers.Protocol.Response.SUCCESS, "success properly reported to user callback");
             }
         }
-        
+
         expected = readXML("commit");
         var response = protocol.commit([featureInsert, featureModify, featureDelete], options);
 
@@ -141,7 +141,7 @@
             featureNS: "http://namespace.org",
             featureType: "type"
         });
-        
+
         var filter = new OpenLayers.Filter.Spatial({
             type: OpenLayers.Filter.Spatial.BBOX,
             value: new OpenLayers.Bounds(-5, -5, 5, 5)
@@ -155,16 +155,16 @@
             t.delay_call(0.1, function() {obj.callback.call(this)});
             return obj;
         };
-        
+
         var response = protocol.filterDelete(filter, {
             callback: function() {
                 t.ok("user callback function called");
             }
         });
-    
+
         OpenLayers.Request.POST = _POST;
     }
-    
+
     function test_abort(t) {
         t.plan(1);
         var protocol = new OpenLayers.Protocol.WFS({
@@ -172,7 +172,7 @@
             featureNS: "http://example.com#namespace",
             featureType: "type"
         });
-        
+
         var response = {
             priv: {
                 abort: function() {
@@ -180,14 +180,14 @@
                 }
             }
         };
-        
+
         // call abort with mocked response
         var aborted = false;
         protocol.abort(response);
         t.eq(aborted, true, "abort called on response.priv");
 
     }
-    
+
     function test_fromWMSLayer(t) {
         t.plan(8);
         var map = new OpenLayers.Map("map", {
@@ -203,18 +203,66 @@
         t.eq(protocol.featureType, "states", "typeName correctly extracted");
         t.eq(protocol.srsName, "EPSG:1234", "srsName set correctly");
         t.eq(protocol.version, "1.1.0", "version set correctly");
-        
+
         layer.params["LAYERS"] = ["topp:street_centerline", "topp:states"];
         layer.projection = new OpenLayers.Projection("EPSG:900913");
         protocol = OpenLayers.Protocol.WFS.fromWMSLayer(layer);
         t.eq(protocol.featurePrefix, "topp", "featurePrefix from layer param array");
-        t.eq(protocol.featureType, "street_centerline", "first layer from layer param array as featureType"); 
-        t.eq(protocol.srsName, "EPSG:900913", "projection from layer preferred"); 
+        t.eq(protocol.featureType, "street_centerline", "first layer from layer param array as featureType");
+        t.eq(protocol.srsName, "EPSG:900913", "projection from layer preferred");
     }
 
+    function test_readFormat(t) {
+        t.plan(1);
+
+        var protocol = new OpenLayers.Protocol.WFS({
+            url: "http://some.url.org",
+            featureNS: "http://namespace.org",
+            featureType: "type",
+            formatOptions: {outputFormat: 'json'},
+            readFormat: new OpenLayers.Format.GeoJSON()
+        });
+
+        var request = {};
+        request.responseText = '{"type":"FeatureCollection","features":[{"type":"Feature","id":"V_HECTOPUNTEN.108411","geometry":{"type":"MultiPoint","coordinates":[[190659.467,349576.19]]},"geometry_name":"ORA_GEOMETRY","properties":{"WEGNUMMER":"002","HECTOMTRNG_ORG":2200,"HECTOMTRNG":"220.00","bbox":[190659.467,349576.19,190659.467,349576.19]}}]}';
+        var features = protocol.parseResponse(request);
+        t.eq(features.length, 1, "the right format is used to read the request (GeoJSON)");
+ 	}
+
+    function test_readOptions(t) {
+        t.plan(1);
+
+        var protocol = new OpenLayers.Protocol.WFS({
+            url: "http://some.url.org",
+            version: "1.1.0",
+            featureNS: "http://namespace.org",
+            featureType: "type",
+            readOptions: {'output': 'object'},
+            parseResponse: function(request, options) {
+                t.eq(options.output, "object", "Options object correctly set to pass on to Format's read");
+            }
+        });
+
+        var _POST = OpenLayers.Request.POST;
+
+        OpenLayers.Request.POST = function(obj) {
+            obj.status = 200;
+            obj.responseText = "foo";
+            obj.options = {};
+            t.delay_call(0.1, function() {obj.callback.call(this)});
+            return obj;
+        };
+
+        protocol.read({
+            callback: function() {}
+        });
+
+        OpenLayers.Request.POST = _POST;
+    }
+
     function readXML(id) {
         var xml = document.getElementById(id).firstChild.nodeValue;
-        return new OpenLayers.Format.XML().read(xml).documentElement;        
+        return new OpenLayers.Format.XML().read(xml).documentElement;
     }
 
   </script>

Modified: sandbox/ahocevar/playground/tests/Protocol.html
===================================================================
--- sandbox/ahocevar/playground/tests/Protocol.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Protocol.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,16 +4,46 @@
   <script type="text/javascript">
 
     function test_initialize(t) {
-        t.plan(3);
+        t.plan(4);
         var options = {};
         var protocol = new OpenLayers.Protocol(options);
 
         t.ok(protocol instanceof OpenLayers.Protocol,
              "new OpenLayers.Protocol returns object" );
         t.eq(protocol.options, options, "constructor sets this.options");
+        t.eq(protocol.options.filter, null, "constructor sets defaultFilter to null");
         t.eq(protocol.autoDestroy, true, "constructor does not modify this.autoDestroy");
     }
     
+    function test_read_defaultFilter(t) {
+        t.plan(4);
+
+        var protocol = new OpenLayers.Protocol({filter: "a"});
+        var options = {};
+        protocol.read(options);
+        // the line below is what happens in Protocol.WFS.v1::read
+        OpenLayers.Util.applyDefaults(options, protocol.options);
+        t.eq(options.filter, "a", "filter from protocol.options applied to options");
+        protocol.destroy();
+
+        var defaultFilter = 'a';
+        var options = {
+            defaultFilter: defaultFilter
+        };
+
+        protocol = new OpenLayers.Protocol(options);
+        var readFilter = 'b';
+        var options = { filter: readFilter };
+
+        protocol.read(options);
+
+        var filter = options.filter;
+        t.ok(filter instanceof OpenLayers.Filter.Logical, "read method merge default filter & options filter to a logical one");
+        t.eq(filter.type, OpenLayers.Filter.Logical.AND, "logical filter type is OpenLayers.Filter.Logical.AND");
+        t.eq(filter.filters, [defaultFilter, readFilter], "read method has merged filters");
+        protocol.destroy();
+    }
+
     function test_destroy(t) {
         t.plan(2);
         var protocol = new OpenLayers.Protocol({

Modified: sandbox/ahocevar/playground/tests/Renderer/Canvas.html
===================================================================
--- sandbox/ahocevar/playground/tests/Renderer/Canvas.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Renderer/Canvas.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -23,7 +23,7 @@
         
         var extent = new OpenLayers.Bounds(1,2,3,4);
         r.resolution = 1;
-        r.setExtent(extent);
+        r.setExtent(extent, true);
         t.ok(r.extent.equals(extent), "extent is correctly set");
         t.eq(r.resolution, null, "resolution nullified");
     }

Modified: sandbox/ahocevar/playground/tests/Renderer/Elements.html
===================================================================
--- sandbox/ahocevar/playground/tests/Renderer/Elements.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Renderer/Elements.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -155,9 +155,10 @@
         r.getNodeType = function(geometry, style) {
             return "div";
         };
-        geometry = {
+        var geometry = {
             id: 'foo',
-            CLASS_NAME: 'bar'
+            CLASS_NAME: 'bar',
+            getBounds: function() {return {bottom: 0}}
         };
         var style = {'backgroundGraphic': 'foo'};
         var featureId = 'dude';
@@ -191,6 +192,10 @@
         
         setUp();
         
+        var geometry = {
+            getBounds: function() {return {bottom: 0}}
+        }
+        
         var r = create_renderer();
         
         var element = document.createElement("div");
@@ -210,9 +215,9 @@
             properDraw = true;
             return {};
         };
-        geometry = {CLASS_NAME: 'OpenLayers.Geometry.Point'};
+        var point = OpenLayers.Util.applyDefaults({CLASS_NAME: 'OpenLayers.Geometry.Point'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(point, style);
         t.ok(properDraw, "drawGeometry called drawPoint when passed a point");
 
         // line string
@@ -221,9 +226,9 @@
             properDraw = true;
             return {};
         };
-        geometry = {id: "foo", CLASS_NAME: 'OpenLayers.Geometry.LineString'};
+        var linestring = OpenLayers.Util.applyDefaults({id: "foo", CLASS_NAME: 'OpenLayers.Geometry.LineString'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(linestring, style);
         t.ok(properDraw, "drawGeometry called drawLineString when passed a line string");
 
         // linear ring
@@ -232,9 +237,9 @@
             properDraw = true;
             return {};
         };
-        geometry = {CLASS_NAME: 'OpenLayers.Geometry.LinearRing'};
+        var linearring = OpenLayers.Util.applyDefaults({CLASS_NAME: 'OpenLayers.Geometry.LinearRing'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(linearring, style);
         t.ok(properDraw, "drawGeometry called drawLinearRing when passed a linear ring");
 
         // polygon
@@ -243,9 +248,9 @@
             properDraw = true;
             return {};
         };
-        geometry = {CLASS_NAME: 'OpenLayers.Geometry.Polygon'};
+        var polygon = OpenLayers.Util.applyDefaults({CLASS_NAME: 'OpenLayers.Geometry.Polygon'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(polygon, style);
         t.ok(properDraw, "drawGeometry called drawPolygon when passed a polygon");
 
         // surface
@@ -254,9 +259,9 @@
             properDraw = true;
             return {};
         }
-        geometry = {CLASS_NAME: 'OpenLayers.Geometry.Surface'};
+        var surface = OpenLayers.Util.applyDefaults({CLASS_NAME: 'OpenLayers.Geometry.Surface'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(surface, style);
         t.ok(properDraw, "drawGeometry called drawSurface when passed a surface");
 
         // rectangle
@@ -265,9 +270,9 @@
             properDraw = true;
             return {};
         };
-        geometry = {CLASS_NAME: 'OpenLayers.Geometry.Rectangle'};
+        var rectangle = OpenLayers.Util.applyDefaults({CLASS_NAME: 'OpenLayers.Geometry.Rectangle'}, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(rectangle, style);
         t.ok(properDraw, "drawGeometry called drawRectangle when passed a rectangle");
 
         // multi-point
@@ -276,12 +281,12 @@
             properDraw = true;
             return {};
         };
-        geometry = {
+        var multipoint = OpenLayers.Util.applyDefaults({
             CLASS_NAME: 'OpenLayers.Geometry.MultiPoint',
-            components: [{CLASS_NAME: 'OpenLayers.Geometry.Point'}]
-        };
+            components: [point]
+        }, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(multipoint, style);
         t.ok(properDraw, "drawGeometry called drawPoint when passed a multi-point");
 
         // multi-linestring
@@ -290,12 +295,12 @@
             properDraw = true;
             return {};
         };
-        geometry = {
+        var multilinestring = OpenLayers.Util.applyDefaults({
             CLASS_NAME: 'OpenLayers.Geometry.MultiLineString',
-            components: [{CLASS_NAME: 'OpenLayers.Geometry.LineString'}]
-        };
+            components: [linestring]
+        }, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(multilinestring, style);
         t.ok(properDraw, "drawGeometry called drawLineString when passed a multi-linestring");
 
         // multi-polygon
@@ -304,12 +309,12 @@
             properDraw = true;
             return {};
         };
-        geometry = {
+        var multipolygon = OpenLayers.Util.applyDefaults({
             CLASS_NAME: 'OpenLayers.Geometry.MultiPolygon',
-            components: [{CLASS_NAME: 'OpenLayers.Geometry.Polygon'}]
-        };
+            components: [polygon]
+        }, geometry);
         style = true;
-        r.drawGeometry(geometry, style);
+        r.drawGeometry(multipolygon, style);
         t.ok(properDraw, "drawGeometry called drawPolygon when passed a multi-polygon");
       
         tearDown();
@@ -489,7 +494,8 @@
         
         var geometry = {
             id: 'foo',
-            CLASS_NAME: 'bar'
+            CLASS_NAME: 'bar',
+            getBounds: function() {return {bottom: 0}}
         };
         var style = {
             graphicZIndex: 10
@@ -555,8 +561,63 @@
         tearDown();        
     }
 
+    function test_Elements_drawGeometry_3(t) {
+        t.plan(2);
 
+        setUp();
 
+        var r = create_renderer();
+        
+        var element = document.createElement("div");
+        r.vectorRoot = element;
+
+        r.nodeFactory = function(id, type) {
+            return document.createElement("div");
+        };
+        var g_Node = null;
+        var b_Node = null;
+        r.drawGeometryNode = function(node, geometry, style) {
+            g_Node = node;
+            return {node: node, complete: true};
+        };
+        r.redrawBackgroundNode = function(id, geometry, style, featureId) {
+            b_Node = r.nodeFactory();
+            b_Node.id = "foo_background";
+            element.appendChild(b_Node);
+        };
+
+        r.getNodeType = function(geometry, style) {
+            return "div";
+        };
+        var geometry = {
+            id: 'foo',
+            CLASS_NAME: 'bar',
+            getBounds: function() {return {bottom: 0}}
+        };
+        var style = {'backgroundGraphic': 'foo'};
+        var featureId = 'dude';
+        r.drawGeometry(geometry, style, featureId);
+        t.ok(b_Node.parentNode == element, "redrawBackgroundNode appended background node");
+
+        var returnNode = function(id) {
+        	return id == "foo_background" ? b_Node : g_Node;
+        }
+       	
+        var _getElement = document.getElementById;
+        document.getElementById = returnNode;
+        OpenLayers.Util.getElement = returnNode;
+
+        style = {};
+        r.drawGeometry(geometry, style, featureId);
+        t.ok(b_Node.parentNode != element, "background node correctly removed")
+            
+        document.getElementById = _getElement;
+
+        tearDown();
+    }
+
+
+
   </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Renderer/SVG.html
===================================================================
--- sandbox/ahocevar/playground/tests/Renderer/SVG.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Renderer/SVG.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -153,7 +153,8 @@
             x: 10000000,
             y: 200000000,
             CLASS_NAME: "OpenLayers.Geometry.Point",
-            id: "foo"
+            id: "foo",
+            getBounds: function() {return {bottom: 0}}
         }
         node.id = geometry.id;
         r.root.appendChild(node);
@@ -391,7 +392,7 @@
         var g = {CLASS_NAME: "OpenLayers.Geometry.Point"}
         var s = {graphicName: "square"};
         
-        t.eq(r.getNodeType(g, s), "use", "Correct node type for well known symbols");
+        t.eq(r.getNodeType(g, s), r.supportUse ? "use" : "svg", "Correct node type for well known symbols");
     }
         
     function test_svg_importsymbol(t) {
@@ -407,11 +408,18 @@
         r.importSymbol("square");
 
         var polygon = document.getElementById(r.container.id + "_defs").firstChild.firstChild;
-
-        var points = polygon.getAttribute("points");
- 
-        t.eq(points.replace(/ /g,''), "0,00,11,11,00,0", "Square symbol rendered correctly");
-        t.ok(r.symbolSize["-square"], "Symbol size cached correctly.");
+        
+        var pass = false;
+        for (var i = 0; i < polygon.points.numberOfItems; i++) {
+            var p = polygon.points.getItem(i);
+            pass = p.x === OpenLayers.Renderer.symbol.square[2*i] && 
+                   p.y === OpenLayers.Renderer.symbol.square[2*i+1];
+            if (!pass) {
+                break;
+            }
+        }
+        t.ok(pass, "Square symbol rendered correctly");
+        t.ok(r.symbolMetrics["-square"], "Symbol metrics cached correctly.");
     }
         
     function test_svg_dashstyle(t) {

Modified: sandbox/ahocevar/playground/tests/Renderer/VML.html
===================================================================
--- sandbox/ahocevar/playground/tests/Renderer/VML.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Renderer/VML.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -48,7 +48,7 @@
             return;
         }
         
-        t.plan(3);
+        t.plan(4);
         
         OpenLayers.Renderer.Elements.prototype._setExtent =
             OpenLayers.Renderer.Elements.prototype.setExtent;
@@ -71,8 +71,9 @@
         
         t.eq(g_SetExtent, true, "Elements.setExtent() called");
         
-        t.ok(r.root.coordorigin == "2,4", "coordorigin is correct");
+        t.ok(r.root.coordorigin == "0,0", "coordorigin is correct");
         t.ok(r.root.coordsize == "4,4", "coordsize is correct");
+        t.eq(r.offset, {x:2, y:4}, "offset is correct");
         
         OpenLayers.Renderer.Elements.prototype.setExtent =
             OpenLayers.Renderer.Elements.prototype._setExtent;
@@ -96,7 +97,36 @@
         t.eq(r.root.style.width, "1px", "root width is correct");
         t.eq(r.root.style.height, "2px", "root height is correct");
     }
+    
+    function test_VML_drawText(t) {
+        if (!OpenLayers.Renderer.VML.prototype.supported()) {
+            t.plan(0);
+            return;
+        }
+        
+        t.plan(2);
 
+        var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
+        
+        r.LABEL_ID_SUFFIX = "";
+        r.getResolution = function() {
+            return 1;
+        };
+
+        var style = {
+            label: "myText",
+            fontColor: "blue"
+        }
+        
+        r.drawText("feature1", style, new OpenLayers.Geometry.Point(1,1));
+        
+        var textbox = document.getElementById("feature1_textbox");
+        
+        t.eq(textbox.innerText, style.label, "label set correctly");
+        t.eq(textbox.style.color, style.fontColor, "font color of label set correctly");
+    }
+
     function test_VML_drawpoint(t) {
         if (!OpenLayers.Renderer.VML.prototype.supported()) {
             t.plan(0);
@@ -127,6 +157,7 @@
         t.plan(4);
         
         var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
         r.resolution = 0.5;
         
         var node = document.createElement('div');
@@ -154,6 +185,7 @@
         t.plan(6);
         
         var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
         r.resolution = 1;
         
         var node = document.createElement('div');
@@ -174,7 +206,7 @@
         r.drawGeometryNode(node, geometry, style);
 
         t.eq(node.childNodes[0].id, "test_fill", "fill child node correctly created");
-        t.eq(node.style.left, "-3px", "x of insertion point with calculated xOffset correct");
+        t.eq(node.style.left, "-2px", "x of insertion point with calculated xOffset correct");
         t.eq(node.style.top, "-3px", "y of insertion point with calculated yOffset correct");
         
         style.rotation = 90;
@@ -182,7 +214,7 @@
         r.drawGeometryNode(node, geometry, style);
         
         t.eq(node.childNodes[1].id, "test_image", "image child node correctly created");
-        t.eq(node.style.left, "-4px", "x of insertion point of rotated image correct");
+        t.eq(node.style.left, "-3px", "x of insertion point of rotated image correct");
         t.eq(node.style.top, "-4px", "y of insertion point of rotated image correct");
     }
 
@@ -235,6 +267,7 @@
         t.plan(8);
         
         var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
         r.resolution = 0.5;
         
         var node = document.createElement('div');
@@ -272,9 +305,10 @@
             return;
         }
         
-        t.plan(2);
+        t.plan(3);
         
         var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
         r.resolution = 0.5;
         
         g_SetNodeDimension = false;
@@ -284,30 +318,16 @@
         
         var node = document.createElement('div');
         
-        var linearRing = {
-            components: [{
-                x: 1,
-                y: 2
-            },{
-                x: 3,
-                y: 4
-            }]
-        };
-        var linearRing2 = {
-            components: [{
-                x: 5,
-                y: 6
-            },{
-                x: 7,
-                y: 8
-            }]
-        };
-        var geometry = {
-            components: [linearRing, linearRing2]
-        };
+        var geometry = OpenLayers.Geometry.fromWKT(
+            "POLYGON((1 2, 3 4), (5 6, 7 8))"
+        );
         r.drawPolygon(node, geometry, true);
         t.ok(g_SetNodeDimension, "setNodeDimension is called");
-        t.eq(node.path, "m 2,4 l 6,8 x m 10,12 l 14,16 x e", "path attribute is correct");
+        t.eq(node.path, "m 2,4 l 6,8 2,4 x m 10,12 l 14,16 10,12 e", "path attribute is correct - inner ring has no area and is not closed");
+
+        geometry.components[1].addComponent(new OpenLayers.Geometry.Point(8, 7));
+        r.drawPolygon(node, geometry, true);
+        t.eq(node.path, "m 2,4 l 6,8 2,4 x m 10,12 l 14,16 16,14 10,12 x e", "path attribute is correct - inner ring has an area and is closed");        
     }
     
     function test_VML_drawrectangle(t) {
@@ -319,6 +339,7 @@
         t.plan(4);
         
         var r = new OpenLayers.Renderer.VML(document.body);
+        r.offset = {x: 0, y: 0};
         r.resolution = 0.5;
         
         var node = document.createElement('div');
@@ -360,8 +381,11 @@
             return;
         }
 
-        t.plan(2);
+        t.plan(4);
         
+        OpenLayers.Renderer.symbol.rect1 = [0,0, 10,0, 10,4, 0,4, 0,0];
+        OpenLayers.Renderer.symbol.rect2 = [0,0, 4,0, 4,10, 0,10, 0,0];
+
         var r = new OpenLayers.Renderer.VML(document.body);
 
         var cache = r.importSymbol("square");
@@ -369,6 +393,15 @@
         t.eq(cache.path, "m 0 0 l 0 1 1 1 1 0 0 0 x e", "Square symbol rendered correctly");
         t.ok(r.symbolCache["-square"], "Symbol has been cached correctly.");
         
+        cache = r.importSymbol("rect1");
+        t.eq(cache.bottom, -3, "coordorigin bottom of landscape symbol set to -3 to move topmost part to the bottom (we are flipping y!)");
+        
+        cache = r.importSymbol("rect2");
+        t.eq(cache.left, -3, "coordorigin left of portrait symbol set to -3 to move leftmost part to the right");
+        
+        delete OpenLayers.Renderer.symbol.rect1;
+        delete OpenLayers.Renderer.symbol.rect2;
+        
     }
     
     function test_vml_dashstyle(t) {

Modified: sandbox/ahocevar/playground/tests/Request.html
===================================================================
--- sandbox/ahocevar/playground/tests/Request.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Request.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -318,6 +318,97 @@
         
     }
 
+    function test_ProxyHost(t) {
+        t.plan(4);
+
+        /*
+         * Setup
+         */
+
+        setup();
+
+        var expectedURL;
+
+        var _ProxyHost = OpenLayers.ProxyHost;
+
+        var proto = OpenLayers.Request.XMLHttpRequest.prototype;
+        var _open = proto.open;
+        var log = [];
+        proto.open = function(method, url, async, user, password) {
+            log.push(url);
+        };
+
+        /*
+         * Test
+         */
+
+        // 2 tests
+        log = [];
+        OpenLayers.ProxyHost = "http://fooproxy/?url=";
+        expectedURL = "http://fooproxy/?url=http%3A%2F%2Fbar%3Fk1%3Dv1%26k2%3Dv2";        
+        OpenLayers.Request.GET({url: "http://bar?k1=v1&k2=v2"});
+        t.eq(log.length, 1, "[1] XHR.open called once");
+        t.eq(log[0], expectedURL, "[1] the URL used for XHR is correct (" + log[0] + ")");
+
+        // 2 tests
+        log = []
+        OpenLayers.ProxyHost = function(url) {
+            var p = OpenLayers.Util.getParameters(url);
+            var p = OpenLayers.Util.getParameterString(p);
+            return "http://barproxy/?" + p;
+        };
+        expectedURL = "http://barproxy/?k1=v1&k2=v2";
+        OpenLayers.Request.GET({url: "http://bar?k1=v1&k2=v2"});
+        t.eq(log.length, 1, "[2] XHR.open called once");
+        t.eq(log[0], expectedURL, "[2] the URL used for XHR is correct (" + log[0] + ")");
+
+        /*
+         * Teardown
+         */
+
+        OpenLayers.Request.XMLHttpRequest.prototype.open = _open;
+        OpenLayers.ProxyHost = _ProxyHost;
+        teardown();
+    }
+
+    function test_abort(t) {
+
+        t.plan(0);
+
+        var sendCalled;
+
+        // set up
+
+        var _open = OpenLayers.Request.XMLHttpRequest.prototype.open;
+        OpenLayers.Request.XMLHttpRequest.prototype.open = function() {
+            this.readyState = OpenLayers.Request.XMLHttpRequest.OPENED;
+        };
+
+        var _setRequestHeader = OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader;
+        OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader = function() {};
+
+        var _send = OpenLayers.Request.XMLHttpRequest.prototype.send;
+        OpenLayers.Request.XMLHttpRequest.prototype.send = function() {
+            sendCalled = true;
+        };
+
+        // test
+
+        sendCalled = false;
+        OpenLayers.Request.issue().abort();
+
+        t.delay_call(0.5, function() {
+            if (sendCalled) {
+                t.fail("Send should not be called because request is aborted");
+            }
+
+            // tear down
+            OpenLayers.Request.XMLHttpRequest.prototype.open = _open;
+            OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader = _setRequestHeader;
+            OpenLayers.Request.XMLHttpRequest.prototype.send = _send;
+        });
+    }
+
     </script>
 </head>
 <body>

Modified: sandbox/ahocevar/playground/tests/Rule.html
===================================================================
--- sandbox/ahocevar/playground/tests/Rule.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Rule.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -43,7 +43,7 @@
     
     function test_clone(t) {
         
-        t.plan(7);
+        t.plan(9);
         
         var rule = new OpenLayers.Rule({
             name: "test rule",
@@ -81,7 +81,31 @@
         
         rule.destroy();
         clone.destroy();
+
+        // test multiple symbolizers
+        rule = new OpenLayers.Rule({
+            name: "test rule",
+            minScaleDenominator: 10,
+            maxScaleDenominator: 20,
+            filter: new OpenLayers.Filter.Comparison({
+                type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                property: "prop",
+                value: "value"
+            }),
+            symbolizers: [
+                new OpenLayers.Symbolizer.Line({
+                    strokeColor: "black"
+                })
+            ]
+        });
+        clone = rule.clone();
+
+        t.eq(clone.symbolizers.length, 1, "clone has one symbolizer");
+        t.ok(clone.symbolizers[0] !== rule.symbolizers[0], "clone has different symbolizers than original");
         
+        clone.destroy();
+        rule.destroy();
+        
     }
 
     function test_Rule_destroy(t) {


Property changes on: sandbox/ahocevar/playground/tests/Strategy
___________________________________________________________________
Modified: svn:mergeinfo
   - 
   + /trunk/openlayers/tests/Strategy:7565-7706,7733-10919

Copied: sandbox/ahocevar/playground/tests/Strategy/Filter.html (from rev 10919, trunk/openlayers/tests/Strategy/Filter.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Strategy/Filter.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Strategy/Filter.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../lib/OpenLayers.js"></script>
+<script>
+
+var features = [];
+for (var i=0; i<20; ++i) {
+    features.push(
+        new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(0, 0), {index: i}
+        )
+    );
+}
+
+var filter = new OpenLayers.Filter.Comparison({
+    type: OpenLayers.Filter.Comparison.LESS_THAN,
+    property: "index",
+    value: 10
+});
+
+function test_initialize(t) {
+    
+    t.plan(4);
+    
+    var strategy = new OpenLayers.Strategy.Filter({filter: filter});
+
+    t.ok(strategy instanceof OpenLayers.Strategy, "is strategy");
+    t.ok(strategy instanceof OpenLayers.Strategy.Filter, "is filter strategy");
+    
+    t.ok(strategy.filter === filter, "has filter");
+    
+    strategy.destroy();
+    
+    try {
+        strategy = new OpenLayers.Strategy.Filter();
+        t.ok(true, "strategy without filter works");
+    } catch (err) {
+        t.fail("strategy without filter should not throw");
+    }
+    
+
+}
+
+function test_autoActivate(t) {
+
+    t.plan(2);
+
+    var strategy = new OpenLayers.Strategy.Filter({filter: filter});
+    
+    var layer = new OpenLayers.Layer.Vector(null, {
+        strategies: [strategy]
+    });
+    
+    t.ok(!strategy.active, "strategy not active before adding to map");
+
+    var map = new OpenLayers.Map({
+        div: "map",
+        allOverlays: true,
+        layers: [layer],
+        center: new OpenLayers.LonLat(0, 0),
+        zoom: 1
+    });
+
+    t.ok(strategy.active, "strategy active after adding to map");
+    
+    map.destroy();
+    
+}
+
+function test_setFilter(t) {
+    
+    t.plan(7);
+
+    var strategy = new OpenLayers.Strategy.Filter({filter: filter});
+    var layer = new OpenLayers.Layer.Vector(null, {
+        strategies: [strategy]
+    });
+
+    var map = new OpenLayers.Map({
+        div: "map",
+        allOverlays: true,
+        layers: [layer],
+        center: new OpenLayers.LonLat(0, 0),
+        zoom: 1
+    });
+
+    // add all features
+    layer.addFeatures(features);
+    t.eq(features.length, 20, "collection of 20 features")
+    t.eq(layer.features.length, 10, "layer got 10 with filter 'index < 10'");
+    t.eq(strategy.cache.length, 10, "strategy cached 10 with filter 'index < 10'");
+
+    // update filter
+    filter.value = 5;
+    strategy.setFilter(filter);
+    t.eq(layer.features.length, 5, "layer got 5 with filter 'index < 5'");
+    t.eq(strategy.cache.length, 15, "strategy cached 15 with filter 'index < 5'");
+
+    // update filter
+    filter.value = 15;
+    strategy.setFilter(filter);
+    t.eq(layer.features.length, 15, "layer got 15 with filter 'index < 15'");
+    t.eq(strategy.cache.length, 5, "strategy cached 5 with filter 'index < 15'");
+    
+    map.destroy();
+    
+}
+
+
+
+</script></head>
+<body>
+    <div id="map" style="width: 512px; height: 256px" />
+</body>
+</html>
\ No newline at end of file

Modified: sandbox/ahocevar/playground/tests/Strategy/Fixed.html
===================================================================
--- sandbox/ahocevar/playground/tests/Strategy/Fixed.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Strategy/Fixed.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -153,7 +153,7 @@
         ];
 
         // call merge with a mocked up response
-        strategy.merge({features: features});
+        strategy.merge(new OpenLayers.Projection("EPSG:900913"), {features: features});
         
         // confirm that the original features were destroyed
         t.eq(layer.features.length, 2, "old features destroyed");
@@ -177,7 +177,7 @@
         ];
         
         // call merge again with mocked up response
-        strategy.merge({features: features});
+        strategy.merge(new OpenLayers.Projection("EPSG:900913"), {features: features});
 
         // test that feature geometries have not been transformed
         t.geom_eq(layer.features[0].geometry, features[0].geometry, "[same proj] feature 0 geometry not transformed");
@@ -185,6 +185,56 @@
         
     }
 
+    function test_load(t) {
+        t.plan(4);
+
+        // set up
+
+        var log;
+
+        var map = new OpenLayers.Map({
+            div: "map",
+            projection: new OpenLayers.Projection("EPSG:900913"),
+            layers: [new OpenLayers.Layer("", {isBaseLayer: true})]
+        });
+
+        var response = new OpenLayers.Protocol.Response();
+
+        var strategy = new OpenLayers.Strategy.Fixed({
+            merge: function(p, r) {
+                log = {scope: this, projection: p, response: r};
+            }
+        });
+
+        var layer = new OpenLayers.Layer.Vector("vector", {
+            strategies: [strategy],
+            protocol: {
+                read: function(o) {
+                    o.callback.call(o.scope, response);
+                }
+            }
+        });
+
+        map.addLayer(layer);
+
+        // test
+
+        strategy.load();
+
+        // verify that the callback is correctly bound
+        t.ok(log !== undefined,
+             "merge was called");
+        t.ok(log.scope == strategy,
+             "merge called with expected scope");
+        t.eq(log.projection.getCode(), map.getProjectionObject().getCode(),
+             "merge called the map projection as the first arg");
+        t.ok(log.response == response,
+             "merge called with response as the first arg");
+
+        // tear down
+
+        map.destroy();
+    }
   </script>
 </head>
 <body>

Copied: sandbox/ahocevar/playground/tests/Strategy/Refresh.html (from rev 10919, trunk/openlayers/tests/Strategy/Refresh.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Strategy/Refresh.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Strategy/Refresh.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,162 @@
+<html>
+<head>
+  <script src="../../lib/OpenLayers.js"></script>
+  <script type="text/javascript">
+
+    var interval = 5000;
+    
+    function test_initialize(t) {
+        t.plan(2);
+
+        var s = new OpenLayers.Strategy.Refresh({interval: interval});
+        t.ok(typeof s.interval === "number", "interval must be a number");
+        t.eq(s.interval, interval, "ctor sets interval");
+    }
+
+    function test_activate(t) {
+        t.plan(4);
+
+        var l = new OpenLayers.Layer.Vector();
+        l.setVisibility(false);
+        var s = new OpenLayers.Strategy.Refresh();
+        s.setLayer(l);
+
+        t.eq(s.active, false, "not active after construction");
+
+        var activated = s.activate();
+        t.eq(activated, true, "activate returns true");
+        t.eq(s.active, true, "activated after activate");
+        t.ok(l.events.listeners.visibilitychanged[0].obj == s &&
+            l.events.listeners.visibilitychanged[0].func == s.reset,
+            "activates registers visibilitychanged listener");
+    }
+
+    function test_activateWithVisibleLayer(t) {
+        t.plan(5);
+
+        var l = new OpenLayers.Layer.Vector();
+        l.setVisibility(true);
+        var s = new OpenLayers.Strategy.Refresh({interval: interval});
+        s.setLayer(l);
+
+        t.eq(s.active, false, "not active after construction");
+
+        var activated = s.activate();
+        t.eq(activated, true, "activate returns true");
+        t.eq(s.active, true, "activated after activate");
+        t.ok(l.events.listeners.visibilitychanged[0].obj == s &&
+            l.events.listeners.visibilitychanged[0].func == s.reset,
+            "activates registers visibilitychanged listener");
+        t.ok(s.timer !== null, "timer should be set on activate if layer is visible");
+
+        // reset the timer!!
+        s.stop();
+    }
+
+    function test_events(t) {
+        
+        t.plan(1);
+        var log = {
+            visibilitychanged: 0
+        };
+
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector(null, {
+            strategies: [new OpenLayers.Strategy.Refresh({interval: interval})],
+            protocol: new OpenLayers.Protocol({
+                read: function(config) {
+                    config.callback.call(config.scope, {});
+                }
+            }),
+            isBaseLayer: true,
+            eventListeners: {
+                visibilitychanged: function() {
+                    ++log.visibilitychanged;
+                }
+            }            
+        });
+        map.addLayer(layer);
+
+        layer.setVisibility(false);
+        t.eq(log.visibilitychanged, 1, "visibilitychanged triggered");
+        
+        map.destroy();
+        
+    }
+
+    function test_refreshWithNormalProgress(t) {
+        
+        t.plan(1);
+        var log = {
+            refreshcalled: 0
+        };
+
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector(null, {
+            strategies: [new OpenLayers.Strategy.Refresh({
+                interval: interval,
+                refresh: function() {
+                    if (this.layer && this.layer.refresh) {
+                        ++log.refreshcalled;
+                    }
+                }
+            })],
+            protocol: new OpenLayers.Protocol({
+                read: function(config) {
+                    config.callback.call(config.scope, {});
+                }
+            }),
+            isBaseLayer: true
+        });
+        map.addLayer(layer);
+
+        t.delay_call((5 * (interval / 1000)) + 0.5, function() { 
+            t.eq(log.refreshcalled, 5, "number of refreshes");
+            map.destroy();
+        });
+        
+    }
+
+    function test_refreshWithSwitchingVisibility(t) {
+        
+        t.plan(1);
+        var log = {
+            refreshcalled: 0
+        };
+
+        var map = new OpenLayers.Map("map");
+        var layer = new OpenLayers.Layer.Vector(null, {
+            strategies: [new OpenLayers.Strategy.Refresh({
+                interval: interval,
+                refresh: function() {
+                    if (this.layer && this.layer.refresh) {
+                        ++log.refreshcalled;
+                    }
+                }
+            })],
+            protocol: new OpenLayers.Protocol({
+                read: function(config) {
+                    config.callback.call(config.scope, {});
+                }
+            }),
+            isBaseLayer: true
+        });
+        map.addLayer(layer);
+
+        window.setTimeout(function() {
+            layer.setVisibility(false);
+        }, 2.5 * interval);
+        
+        t.delay_call((5 * (interval / 1000)) + 0.5, function() { 
+            t.eq(log.refreshcalled, 2, "number of refreshes");
+            map.destroy();
+        });
+        
+    }
+
+    </script>
+</head>
+<body>
+    <div id="map" style="width: 400px; height: 200px;"></div>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Style.html
===================================================================
--- sandbox/ahocevar/playground/tests/Style.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Style.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -237,7 +237,7 @@
     }
     
     function test_Style_context(t) {
-        t.plan(2);
+        t.plan(4);
         var rule = new OpenLayers.Rule({
             symbolizer: {"Point": {externalGraphic: "${img1}"}},
             filter: new OpenLayers.Filter.Comparison({
@@ -265,6 +265,18 @@
                 }
             }});
         t.eq(style.createSymbolizer(feature).externalGraphic, "foo10.png", "correctly evaluated symbolizer without rule");
+        
+        style = new OpenLayers.Style(
+            {externalGraphic: "${getExternalGraphic}",
+             pointRadius: "${size}"},
+            {context: {
+                getExternalGraphic: function(feature) {
+                    return "foo" + feature.attributes.size + ".png";
+                }
+            }});
+        t.eq(style.createSymbolizer(feature).externalGraphic, "foo10.png", "correctly evaluated symbolizer from context");
+        t.eq(style.createSymbolizer(feature).pointRadius, 10, "correctly evaluated symbolizer from attributes");
+        
     };
         
     function test_Style_findPropertyStyles(t) {
@@ -329,6 +341,44 @@
 
     }
 
+    function test_clone(t) {
+        
+        t.plan(7);
+        
+        var style = new OpenLayers.Style({bar: "baz"}, {
+            name: "test style",
+            rules: [new OpenLayers.Rule({
+                name: "test rule"
+            })],
+            context: {
+                foo: "bar"
+            }
+        });
+        var clone = style.clone();
+        t.eq(clone.name, "test style", "name copied");
+        t.eq(clone.rules[0].name, "test rule", "clone has correct rule");
+        
+        // modify original
+        style.name = "new";
+        style.addRules([new OpenLayers.Rule({
+			name: "new rule"
+		})]);
+        style.context.foo = "baz";
+        
+        // confirm that clone didn't change
+        t.eq(clone.defaultStyle.bar, "baz", "clone has clone of defaultStyle");
+        t.eq(clone.name, "test style", "clone has clone of name");
+        t.eq(clone.rules.length, 1, "clone has clone of rules");
+        t.eq(clone.context.foo, "bar", "clone has clone of context");
+        
+        // confirm that ids are different
+        t.ok(clone.id !== style.id, "clone has different id");
+
+        style.destroy();
+        clone.destroy();
+        
+    }
+
     function test_Style_destroy(t) {
         t.plan(1);
         

Copied: sandbox/ahocevar/playground/tests/Style2.html (from rev 10919, trunk/openlayers/tests/Style2.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Style2.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Style2.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,56 @@
+<html> 
+<head> 
+    <script src="../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(4); 
+
+        var rules = [
+            new OpenLayers.Rule({
+                symbolizer: {fillColor: "red"},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                    property: "type",
+                    value: "fire engine"
+                })
+            }),
+            new OpenLayers.Rule({
+                symbolizer: {fillColor: "yellow"},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                    property: "type",
+                    value: "sports car"
+                })
+            })
+        ];
+        var style = new OpenLayers.Style2({rules: rules}); 
+        t.ok(style instanceof OpenLayers.Style2, "correct type"); 
+        t.eq(style.rules.length, 2, "correct number of rules added");
+        t.ok(style.rules[0] === rules[0], "correct first rule added");
+        t.ok(style.rules[1] === rules[1], "correct second rule added");
+    }
+    
+    function test_destroy(t) {
+        t.plan(1);
+        
+        var style = new OpenLayers.Style2({
+            rules: [
+                new OpenLayers.Rule({
+                    symbolizers: [
+                        new OpenLayers.Symbolizer.Point({
+                            fillColor: "fuchsia"
+                        })
+                    ]
+                })
+            ]
+        });
+        style.destroy();
+        t.ok(!style.rules, "rules array gone");
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Symbolizer/Line.html
===================================================================
--- trunk/openlayers/tests/Symbolizer/Line.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Line.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,42 +0,0 @@
-<html> 
-<head> 
-    <script src="../../lib/OpenLayers.js"></script> 
-    <script type="text/javascript">
-
-    function test_constructor(t) { 
-        t.plan(3); 
-        
-        var symbolizer = new OpenLayers.Symbolizer.Line({foo: "bar"});
-        
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Line, "instance of OpenLayers.Symbolizer.Line");
-        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
-
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        
-        var symbolizer = new OpenLayers.Symbolizer.Line({foo: "bar"});
-        var clone = symbolizer.clone();
-        
-        t.ok(clone instanceof OpenLayers.Symbolizer.Line, "correct type");
-        t.eq(clone.foo, "bar", "clone copies properties");
-        
-    }
-    
-    function test_defaults(t) {
-        t.plan(5);
-        var symbolizer = new OpenLayers.Symbolizer.Line();
-        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
-        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
-        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
-        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
-        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
-    }
-
-
-    </script> 
-</head>
-<body></body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer/Line.html (from rev 10919, trunk/openlayers/tests/Symbolizer/Line.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer/Line.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Line.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,42 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(3); 
+        
+        var symbolizer = new OpenLayers.Symbolizer.Line({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Line, "instance of OpenLayers.Symbolizer.Line");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer.Line({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer.Line, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+    
+    function test_defaults(t) {
+        t.plan(5);
+        var symbolizer = new OpenLayers.Symbolizer.Line();
+        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
+        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
+        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
+        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
+        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Symbolizer/Point.html
===================================================================
--- trunk/openlayers/tests/Symbolizer/Point.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Point.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,52 +0,0 @@
-<html> 
-<head> 
-    <script src="../../lib/OpenLayers.js"></script> 
-    <script type="text/javascript">
-
-    function test_constructor(t) { 
-        t.plan(3); 
-        
-        var symbolizer = new OpenLayers.Symbolizer.Point({foo: "bar"});
-        
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Point, "instance of OpenLayers.Symbolizer.Point");
-        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
-
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        
-        var symbolizer = new OpenLayers.Symbolizer.Point({foo: "bar"});
-        var clone = symbolizer.clone();
-        
-        t.ok(clone instanceof OpenLayers.Symbolizer.Point, "correct type");
-        t.eq(clone.foo, "bar", "clone copies properties");
-        
-    }
-
-    function test_defaults(t) {
-        t.plan(16);
-        var symbolizer = new OpenLayers.Symbolizer.Point();
-        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
-        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
-        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
-        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
-        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
-        t.ok(symbolizer.fillColor === undefined, "no default fillColor");
-        t.ok(symbolizer.fillOpacity === undefined, "no default fillOpacity");
-        t.ok(symbolizer.pointRadius === undefined, "no default pointRadius");
-        t.ok(symbolizer.externalGraphic === undefined, "no default externalGraphic");
-        t.ok(symbolizer.graphicWidth === undefined, "no default graphicWidth");
-        t.ok(symbolizer.graphicHeight === undefined, "no default graphicHeight");
-        t.ok(symbolizer.graphicOpacity === undefined, "no default graphicOpacity");
-        t.ok(symbolizer.graphicXOffset === undefined, "no default graphicXOffset");
-        t.ok(symbolizer.graphicYOffset === undefined, "no default graphicYOffset");
-        t.ok(symbolizer.rotation === undefined, "no default rotation");
-        t.ok(symbolizer.graphicName === undefined, "no default graphicName");
-    }
-
-    </script> 
-</head>
-<body></body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer/Point.html (from rev 10919, trunk/openlayers/tests/Symbolizer/Point.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer/Point.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Point.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,52 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(3); 
+        
+        var symbolizer = new OpenLayers.Symbolizer.Point({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Point, "instance of OpenLayers.Symbolizer.Point");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer.Point({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer.Point, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+
+    function test_defaults(t) {
+        t.plan(16);
+        var symbolizer = new OpenLayers.Symbolizer.Point();
+        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
+        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
+        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
+        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
+        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
+        t.ok(symbolizer.fillColor === undefined, "no default fillColor");
+        t.ok(symbolizer.fillOpacity === undefined, "no default fillOpacity");
+        t.ok(symbolizer.pointRadius === undefined, "no default pointRadius");
+        t.ok(symbolizer.externalGraphic === undefined, "no default externalGraphic");
+        t.ok(symbolizer.graphicWidth === undefined, "no default graphicWidth");
+        t.ok(symbolizer.graphicHeight === undefined, "no default graphicHeight");
+        t.ok(symbolizer.graphicOpacity === undefined, "no default graphicOpacity");
+        t.ok(symbolizer.graphicXOffset === undefined, "no default graphicXOffset");
+        t.ok(symbolizer.graphicYOffset === undefined, "no default graphicYOffset");
+        t.ok(symbolizer.rotation === undefined, "no default rotation");
+        t.ok(symbolizer.graphicName === undefined, "no default graphicName");
+    }
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html
===================================================================
--- trunk/openlayers/tests/Symbolizer/Polygon.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,44 +0,0 @@
-<html> 
-<head> 
-    <script src="../../lib/OpenLayers.js"></script> 
-    <script type="text/javascript">
-
-    function test_constructor(t) { 
-        t.plan(3); 
-        
-        var symbolizer = new OpenLayers.Symbolizer.Polygon({foo: "bar"});
-        
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Polygon, "instance of OpenLayers.Symbolizer.Polygon");
-        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
-
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        
-        var symbolizer = new OpenLayers.Symbolizer.Polygon({foo: "bar"});
-        var clone = symbolizer.clone();
-        
-        t.ok(clone instanceof OpenLayers.Symbolizer.Polygon, "correct type");
-        t.eq(clone.foo, "bar", "clone copies properties");
-        
-    }
-
-    function test_defaults(t) {
-        t.plan(7);
-        var symbolizer = new OpenLayers.Symbolizer.Polygon();
-        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
-        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
-        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
-        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
-        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
-        t.ok(symbolizer.fillColor === undefined, "no default fillColor");
-        t.ok(symbolizer.fillOpacity === undefined, "no default fillOpacity");
-    }
-
-
-    </script> 
-</head>
-<body></body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html (from rev 10919, trunk/openlayers/tests/Symbolizer/Polygon.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Polygon.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,44 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(3); 
+        
+        var symbolizer = new OpenLayers.Symbolizer.Polygon({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Polygon, "instance of OpenLayers.Symbolizer.Polygon");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer.Polygon({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer.Polygon, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+
+    function test_defaults(t) {
+        t.plan(7);
+        var symbolizer = new OpenLayers.Symbolizer.Polygon();
+        t.ok(symbolizer.strokeColor === undefined, "no default strokeColor");
+        t.ok(symbolizer.strokeOpacity === undefined, "no default strokeOpacity");
+        t.ok(symbolizer.strokeWidth === undefined, "no default strokeWidth");
+        t.ok(symbolizer.strokeLinecap === undefined, "no default strokeLinecap");
+        t.ok(symbolizer.strokeDashstyle === undefined, "no default strokeDashstyle");
+        t.ok(symbolizer.fillColor === undefined, "no default fillColor");
+        t.ok(symbolizer.fillOpacity === undefined, "no default fillOpacity");
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Symbolizer/Raster.html
===================================================================
--- trunk/openlayers/tests/Symbolizer/Raster.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Raster.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,32 +0,0 @@
-<html> 
-<head> 
-    <script src="../../lib/OpenLayers.js"></script> 
-    <script type="text/javascript">
-
-    function test_constructor(t) { 
-        t.plan(3); 
-        
-        var symbolizer = new OpenLayers.Symbolizer.Raster({foo: "bar"});
-        
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Raster, "instance of OpenLayers.Symbolizer.Raster");
-        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
-
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        
-        var symbolizer = new OpenLayers.Symbolizer.Raster({foo: "bar"});
-        var clone = symbolizer.clone();
-        
-        t.ok(clone instanceof OpenLayers.Symbolizer.Raster, "correct type");
-        t.eq(clone.foo, "bar", "clone copies properties");
-        
-    }
-
-
-    </script> 
-</head>
-<body></body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer/Raster.html (from rev 10919, trunk/openlayers/tests/Symbolizer/Raster.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer/Raster.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Raster.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,32 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(3); 
+        
+        var symbolizer = new OpenLayers.Symbolizer.Raster({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Raster, "instance of OpenLayers.Symbolizer.Raster");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer.Raster({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer.Raster, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Symbolizer/Text.html
===================================================================
--- trunk/openlayers/tests/Symbolizer/Text.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Text.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,42 +0,0 @@
-<html> 
-<head> 
-    <script src="../../lib/OpenLayers.js"></script> 
-    <script type="text/javascript">
-
-    function test_constructor(t) { 
-        t.plan(3); 
-        
-        var symbolizer = new OpenLayers.Symbolizer.Text({foo: "bar"});
-        
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
-        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Text, "instance of OpenLayers.Symbolizer.Text");
-        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
-
-    }
-    
-    function test_clone(t) {
-        t.plan(2);
-        
-        var symbolizer = new OpenLayers.Symbolizer.Text({foo: "bar"});
-        var clone = symbolizer.clone();
-        
-        t.ok(clone instanceof OpenLayers.Symbolizer.Text, "correct type");
-        t.eq(clone.foo, "bar", "clone copies properties");
-        
-    }
-
-    function test_defaults(t) {
-        t.plan(5);
-        var symbolizer = new OpenLayers.Symbolizer.Point();
-        t.ok(symbolizer.label === undefined, "no default label");
-        t.ok(symbolizer.fontFamily === undefined, "no default fontFamily");
-        t.ok(symbolizer.fontSize === undefined, "no default fontSize");
-        t.ok(symbolizer.fontWeight === undefined, "no default fontWeight");
-        t.ok(symbolizer.fontStyle === undefined, "no default fontStyle");
-    }
-
-
-    </script> 
-</head>
-<body></body> 
-</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer/Text.html (from rev 10919, trunk/openlayers/tests/Symbolizer/Text.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer/Text.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer/Text.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,42 @@
+<html> 
+<head> 
+    <script src="../../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(3); 
+        
+        var symbolizer = new OpenLayers.Symbolizer.Text({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "instance of OpenLayers.Symbolizer");
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer.Text, "instance of OpenLayers.Symbolizer.Text");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer.Text({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer.Text, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+
+    function test_defaults(t) {
+        t.plan(5);
+        var symbolizer = new OpenLayers.Symbolizer.Point();
+        t.ok(symbolizer.label === undefined, "no default label");
+        t.ok(symbolizer.fontFamily === undefined, "no default fontFamily");
+        t.ok(symbolizer.fontSize === undefined, "no default fontSize");
+        t.ok(symbolizer.fontWeight === undefined, "no default fontWeight");
+        t.ok(symbolizer.fontStyle === undefined, "no default fontStyle");
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Copied: sandbox/ahocevar/playground/tests/Symbolizer.html (from rev 10919, trunk/openlayers/tests/Symbolizer.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Symbolizer.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Symbolizer.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,31 @@
+<html> 
+<head> 
+    <script src="../lib/OpenLayers.js"></script> 
+    <script type="text/javascript">
+
+    function test_constructor(t) { 
+        t.plan(2); 
+        
+        var symbolizer = new OpenLayers.Symbolizer({foo: "bar"});
+        
+        t.ok(symbolizer instanceof OpenLayers.Symbolizer, "correct type");
+        t.eq(symbolizer.foo, "bar", "constructor applies config properties");
+
+    }
+    
+    function test_clone(t) {
+        t.plan(2);
+        
+        var symbolizer = new OpenLayers.Symbolizer({foo: "bar"});
+        var clone = symbolizer.clone();
+        
+        t.ok(clone instanceof OpenLayers.Symbolizer, "correct type");
+        t.eq(clone.foo, "bar", "clone copies properties");
+        
+    }
+
+
+    </script> 
+</head>
+<body></body> 
+</html> 

Deleted: sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html
===================================================================
--- trunk/openlayers/tests/Tile/Image/IFrame.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,200 +0,0 @@
-<html>
-<head>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
-    var isOpera   = (navigator.userAgent.indexOf("Opera") != -1);
-    var isIE      = (navigator.userAgent.indexOf("MSIE") != -1);
-
-    var map, layer;
-    var position = new OpenLayers.Pixel(20,30);
-    var bounds   = new OpenLayers.Bounds(1,2,3,4);
-    var url      = "http://www.openlayers.org/dev/tests/tileimage";
-    var size     = new OpenLayers.Size(5,6);
-    var name     = "OpenaLayers WMS";
-    var wmsUrl   = "http://labs.metacarta.com/wms/vmap0?";
-    
-    function test_Tile_Image_IFrame_create (t) {
-        t.plan( 3 );
-        map   = new OpenLayers.Map('map');
-        var bar = new Array(205).join("1234567890");
-        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic', foo: bar}, {tileOptions: {maxGetUrlLength: 2048}}); 
-        map.addLayer(layer);
-
-        var tile = layer.addTile(bounds, position);
-        tile.renderTile();
-        tile.positionImage();
-        t.eq(tile.imgDiv.firstChild.nodeName.toLowerCase(), "iframe", "IFrame used for long URL");
-        
-        layer.mergeNewParams({foo: null});
-        tile.renderTile();
-        tile.positionImage();
-        t.eq(tile.imgDiv.nodeName.toLowerCase(), "img", "IMG used for short URL");
-        
-        tile.maxGetUrlLength = 0;
-        tile.renderTile();
-        tile.positionImage();
-        t.eq(tile.imgDiv.firstChild.nodeName.toLowerCase(), "iframe", "IFrame used when maxGetUrlLength is 0");
-        
-        tile.destroy();
-        layer.destroy();
-        map.destroy();
-    }
-
-    function test_Tile_Image_IFrame_clear (t) {
-        t.plan( 1 );
-        
-        map   = new OpenLayers.Map('map');
-        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
-        map.addLayer(layer);  
-        tile = layer.addTile(bounds, position);
-        tile.draw();
-        tile.clear();
-
-        t.eq(
-            tile.imgDiv.firstChild.nodeName.toLowerCase(), "div",
-            "IFrame successfully removed from DOM");
-        tile.destroy();
-        layer.destroy();
-        map.destroy();
-    }
-
-    function test_Tile_Image_IFrame_initImgDiv (t) {
-        t.plan( 4 );
-
-        map   = new OpenLayers.Map('map');
-        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
-        map.addLayer(layer);  
-        tile = layer.addTile(bounds, position);
-        tile.url = layer.getURL(bounds);
-        tile.initImgDiv();
-
-        if(isMozilla) {
-            t.ok( tile.imgDiv instanceof HTMLElement, "tile.iFrame successfully created.");
-        }
-        else {
-            t.ok( tile.imgDiv != null, "tile.iFrame successfully created.");
-        }
-        t.eq( tile.imgDiv.id, tile.id, "imgDiv id correctly set.");
-        t.eq( tile.imgDiv.className, "olTileImage", "iFrame's className correctly set.");
-        t.ok( tile.imgDiv.map == map, "map correctly added to iFrame.");
-
-        map.destroy();
-    }
-
-    function test_Tile_Image_IFrame_createImgDiv (t) {
-        t.plan( 3 );
-
-        map   = new OpenLayers.Map('map');
-        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
-        map.addLayer(layer);  
-        var tile = layer.addTile(bounds, position);
-        tile.renderTile();
-        var imgDiv = tile.imgDiv;
-        var iFrame    = imgDiv.firstChild;
-        var eventPane = imgDiv.childNodes[1];
-
-        if(isIE) {
-            t.ok(iFrame != null, "IFrame successfully created.");
-            t.eq(eventPane.style.backgroundColor, '#ffffff', "backgroundColor of overlay pane is set in InternetExplorer.");
-            t.eq(eventPane.style.filter, 'chroma(color=#FFFFFF)', "filter of overlay pane is set in InternetExplorer.");
-        }
-        else {
-            t.ok(iFrame instanceof HTMLElement, "IFrame successfully created.");
-            t.ok(true, 'Skip eventPane backgroundColor test outside IE');
-            t.ok(true, 'Skip eventPane filter test outside IE');
-        }
-        map.destroy();
-    }
-
-    function test_Tile_Image_IFrame_createIFrame (t) {
-        t.plan( 8 );
-        
-        map   = new OpenLayers.Map('map');
-        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
-        map.addLayer(layer);  
-        var tile = layer.addTile(bounds, position);
-        var iFrame = tile.createIFrame();
-
-        var id = tile.id+'_iFrame';
-        t.eq(iFrame.id, id, "iframe id correctly set.");
-        t.eq(iFrame.name, id, "iframe name correctly set.");
-        
-        if(isIE) {
-            t.eq(iFrame.style.backgroundColor, '#ffffff', "backgroundColor correctly set.");
-            t.eq(iFrame.style.filter, 'chroma(color=#FFFFFF)', "filter correctly set.");
-        }
-        else {
-            t.eq(iFrame.style.backgroundColor, 'transparent', "backgroundColor correctly set.");
-            t.ok(true, "Skip filter test outside InternetExplorer.");
-        }
-        t.eq( iFrame.scrolling, 'no', "no scrolling");
-        t.eq( parseFloat(iFrame.marginWidth), 0, "no margin width");
-        t.eq( parseFloat(iFrame.marginHeight), 0, "no margin height");
-        t.eq( parseFloat(iFrame.frameBorder), 0, "no iframe border");
-    }
-
-    function test_Tile_Image_IFrame_createRequestForm (t) {
-        t.plan( 6 );
-
-        var tParams = {
-            SERVICE: "WMS", VERSION: "1.1.1",
-            REQUEST: "GetMap", STYLES: "",
-            EXCEPTIONS: "application/vnd.ogc.se_inimage", FORMAT: "image/jpeg",
-            SRS: "EPSG:4326", BBOX: [1,2,3,4],
-            WIDTH: String(size.w), HEIGHT: String(size.h)
-        };
-        var newLayer = new OpenLayers.Layer.WMS("Name",
-                     "http://labs.metacarta.com/TESTURL",
-                     tParams,
-                     {tileSize: size, tileOptions: {maxGetUrlLength: 0}});  
-        map = new OpenLayers.Map('map'); 
-        map.addLayer(newLayer);  
-        tile = newLayer.addTile(bounds, position);
-        tile.url = newLayer.getURL(bounds);
-        tile.initImgDiv();
-
-        tile.url = newLayer.getURL(bounds);
-        var form = tile.createRequestForm();
-        if(isMozilla) {
-            t.ok( form instanceof HTMLElement, "created html form successfully.");
-        }
-        else {
-            t.ok( form != null, "created html form successfully.");
-        }
-
-        
-        var cacheId = newLayer.params["_OLSALT"];
-        cacheId     = (cacheId ? cacheId + "_" : "") + tile.bounds.toBBOX();
-        var url = OpenLayers.Util.urlAppend(newLayer.url, cacheId);
-
-        t.eq( form.method.toLowerCase(), 'post', "form method correctly set.");
-        t.eq( form.target, tile.id+'_iFrame', "form target correctly set.");
-        t.eq( form.action, url, "form action correctly set.");
-
-        var formParams = {};
-        var children = form.childNodes;
-        for(var i=0; i<form.childNodes.length; i++) {
-            formParams[children[i].name] = children[i].value
-        }
-        newLayer.params.BBOX = newLayer.params.BBOX.join(",");
-        t.eq(newLayer.params, formParams, "html form elements equal layer's parameters.");
-
-        tile.draw();
-        tile.clear();
-        tile.createRequestForm();
-        t.ok(
-            tile.imgDiv.firstChild.nodeName == "IFRAME",
-            "Iframe has been reinserted properly"
-        );
-        
-        tile.destroy();
-        newLayer.destroy();
-        map.destroy();
-    }
-</script>
-</head>
-<body>
-<div id="map" style="height:550px;width:500px"></div>
-</body>
-</html>

Copied: sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html (from rev 10919, trunk/openlayers/tests/Tile/Image/IFrame.html)
===================================================================
--- sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/Tile/Image/IFrame.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,200 @@
+<html>
+<head>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
+    var isOpera   = (navigator.userAgent.indexOf("Opera") != -1);
+    var isIE      = (navigator.userAgent.indexOf("MSIE") != -1);
+
+    var map, layer;
+    var position = new OpenLayers.Pixel(20,30);
+    var bounds   = new OpenLayers.Bounds(1,2,3,4);
+    var url      = "http://www.openlayers.org/dev/tests/tileimage";
+    var size     = new OpenLayers.Size(5,6);
+    var name     = "OpenaLayers WMS";
+    var wmsUrl   = "http://labs.metacarta.com/wms/vmap0?";
+    
+    function test_Tile_Image_IFrame_create (t) {
+        t.plan( 3 );
+        map   = new OpenLayers.Map('map');
+        var bar = new Array(205).join("1234567890");
+        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic', foo: bar}, {tileOptions: {maxGetUrlLength: 2048}}); 
+        map.addLayer(layer);
+
+        var tile = layer.addTile(bounds, position);
+        tile.renderTile();
+        tile.positionImage();
+        t.eq(tile.imgDiv.firstChild.nodeName.toLowerCase(), "iframe", "IFrame used for long URL");
+        
+        layer.mergeNewParams({foo: null});
+        tile.renderTile();
+        tile.positionImage();
+        t.eq(tile.imgDiv.nodeName.toLowerCase(), "img", "IMG used for short URL");
+        
+        tile.maxGetUrlLength = 0;
+        tile.renderTile();
+        tile.positionImage();
+        t.eq(tile.imgDiv.firstChild.nodeName.toLowerCase(), "iframe", "IFrame used when maxGetUrlLength is 0");
+        
+        tile.destroy();
+        layer.destroy();
+        map.destroy();
+    }
+
+    function test_Tile_Image_IFrame_clear (t) {
+        t.plan( 1 );
+        
+        map   = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
+        map.addLayer(layer);  
+        tile = layer.addTile(bounds, position);
+        tile.draw();
+        tile.clear();
+
+        t.eq(
+            tile.imgDiv.firstChild.nodeName.toLowerCase(), "div",
+            "IFrame successfully removed from DOM");
+        tile.destroy();
+        layer.destroy();
+        map.destroy();
+    }
+
+    function test_Tile_Image_IFrame_initImgDiv (t) {
+        t.plan( 4 );
+
+        map   = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
+        map.addLayer(layer);  
+        tile = layer.addTile(bounds, position);
+        tile.url = layer.getURL(bounds);
+        tile.initImgDiv();
+
+        if(isMozilla) {
+            t.ok( tile.imgDiv instanceof HTMLElement, "tile.iFrame successfully created.");
+        }
+        else {
+            t.ok( tile.imgDiv != null, "tile.iFrame successfully created.");
+        }
+        t.eq( tile.imgDiv.id, tile.id, "imgDiv id correctly set.");
+        t.eq( tile.imgDiv.className, "olTileImage", "iFrame's className correctly set.");
+        t.ok( tile.imgDiv.map == map, "map correctly added to iFrame.");
+
+        map.destroy();
+    }
+
+    function test_Tile_Image_IFrame_createImgDiv (t) {
+        t.plan( 3 );
+
+        map   = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
+        map.addLayer(layer);  
+        var tile = layer.addTile(bounds, position);
+        tile.renderTile();
+        var imgDiv = tile.imgDiv;
+        var iFrame    = imgDiv.firstChild;
+        var eventPane = imgDiv.childNodes[1];
+
+        if(isIE) {
+            t.ok(iFrame != null, "IFrame successfully created.");
+            t.eq(eventPane.style.backgroundColor, '#ffffff', "backgroundColor of overlay pane is set in InternetExplorer.");
+            t.eq(eventPane.style.filter, 'chroma(color=#FFFFFF)', "filter of overlay pane is set in InternetExplorer.");
+        }
+        else {
+            t.ok(iFrame instanceof HTMLElement, "IFrame successfully created.");
+            t.ok(true, 'Skip eventPane backgroundColor test outside IE');
+            t.ok(true, 'Skip eventPane filter test outside IE');
+        }
+        map.destroy();
+    }
+
+    function test_Tile_Image_IFrame_createIFrame (t) {
+        t.plan( 8 );
+        
+        map   = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer.WMS(name, wmsUrl, {layers: 'basic'}, {tileOptions: {maxGetUrlLength: 0}}); 
+        map.addLayer(layer);  
+        var tile = layer.addTile(bounds, position);
+        var iFrame = tile.createIFrame();
+
+        var id = tile.id+'_iFrame';
+        t.eq(iFrame.id, id, "iframe id correctly set.");
+        t.eq(iFrame.name, id, "iframe name correctly set.");
+        
+        if(isIE) {
+            t.eq(iFrame.style.backgroundColor, '#ffffff', "backgroundColor correctly set.");
+            t.eq(iFrame.style.filter, 'chroma(color=#FFFFFF)', "filter correctly set.");
+        }
+        else {
+            t.eq(iFrame.style.backgroundColor, 'transparent', "backgroundColor correctly set.");
+            t.ok(true, "Skip filter test outside InternetExplorer.");
+        }
+        t.eq( iFrame.scrolling, 'no', "no scrolling");
+        t.eq( parseFloat(iFrame.marginWidth), 0, "no margin width");
+        t.eq( parseFloat(iFrame.marginHeight), 0, "no margin height");
+        t.eq( parseFloat(iFrame.frameBorder), 0, "no iframe border");
+    }
+
+    function test_Tile_Image_IFrame_createRequestForm (t) {
+        t.plan( 6 );
+
+        var tParams = {
+            SERVICE: "WMS", VERSION: "1.1.1",
+            REQUEST: "GetMap", STYLES: "",
+            EXCEPTIONS: "application/vnd.ogc.se_inimage", FORMAT: "image/jpeg",
+            SRS: "EPSG:4326", BBOX: [1,2,3,4],
+            WIDTH: String(size.w), HEIGHT: String(size.h)
+        };
+        var newLayer = new OpenLayers.Layer.WMS("Name",
+                     "http://labs.metacarta.com/TESTURL",
+                     tParams,
+                     {tileSize: size, tileOptions: {maxGetUrlLength: 0}});  
+        map = new OpenLayers.Map('map'); 
+        map.addLayer(newLayer);  
+        tile = newLayer.addTile(bounds, position);
+        tile.url = newLayer.getURL(bounds);
+        tile.initImgDiv();
+
+        tile.url = newLayer.getURL(bounds);
+        var form = tile.createRequestForm();
+        if(isMozilla) {
+            t.ok( form instanceof HTMLElement, "created html form successfully.");
+        }
+        else {
+            t.ok( form != null, "created html form successfully.");
+        }
+
+        
+        var cacheId = newLayer.params["_OLSALT"];
+        cacheId     = (cacheId ? cacheId + "_" : "") + tile.bounds.toBBOX();
+        var url = OpenLayers.Util.urlAppend(newLayer.url, cacheId);
+
+        t.eq( form.method.toLowerCase(), 'post', "form method correctly set.");
+        t.eq( form.target, tile.id+'_iFrame', "form target correctly set.");
+        t.eq( form.action, url, "form action correctly set.");
+
+        var formParams = {};
+        var children = form.childNodes;
+        for(var i=0; i<form.childNodes.length; i++) {
+            formParams[children[i].name] = children[i].value
+        }
+        newLayer.params.BBOX = newLayer.params.BBOX.join(",");
+        t.eq(newLayer.params, formParams, "html form elements equal layer's parameters.");
+
+        tile.draw();
+        tile.clear();
+        tile.createRequestForm();
+        t.ok(
+            tile.imgDiv.firstChild.nodeName == "IFRAME",
+            "Iframe has been reinserted properly"
+        );
+        
+        tile.destroy();
+        newLayer.destroy();
+        map.destroy();
+    }
+</script>
+</head>
+<body>
+<div id="map" style="height:550px;width:500px"></div>
+</body>
+</html>

Modified: sandbox/ahocevar/playground/tests/Tile/Image.html
===================================================================
--- sandbox/ahocevar/playground/tests/Tile/Image.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Tile/Image.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -87,6 +87,29 @@
         t.ok( clone.imgDiv == null, "clone's imgDiv was not copied");
     }
     
+    function test_Tile_Image_IFrame_viewRequestID (t) {
+        t.plan( 2 );
+        var map   = new OpenLayers.Map('map');
+        var layer = new OpenLayers.Layer.WMS(
+            "Name",
+            "http://labs.metacarta.com/TESTURL?",
+            {layers: 'basic'}
+        ); 
+        map.addLayer(layer);
+
+        var position = new OpenLayers.Pixel(20,30);
+        var bounds = new OpenLayers.Bounds(1,2,3,4);
+        tile = layer.addTile(bounds, position);
+        tile.renderTile();
+        t.eq(tile.imgDiv.viewRequestID, map.viewRequestID, "viewRequestID correct after renderTile");
+        map.viewRequestID++;
+        tile.renderTile();
+        t.eq(tile.imgDiv.viewRequestID, map.viewRequestID, "viewRequestID correct after subsequent renderTile");
+        tile.destroy();
+        layer.destroy();
+        map.destroy();
+    }
+
     function test_Tile_Image_draw (t) {
         t.plan( 7 );
 

Modified: sandbox/ahocevar/playground/tests/Util.html
===================================================================
--- sandbox/ahocevar/playground/tests/Util.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/Util.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,6 @@
 <html>
 <head>
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
   <script>
     var custom$ = function() {};
     window.$ = custom$;
@@ -8,6 +9,24 @@
   <script type="text/javascript">
     var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
     var map; 
+
+    function test_isElement(t) {
+        t.plan(3);
+
+        // set up
+        var o;
+
+        // tests
+        o = {};
+        t.eq(OpenLayers.Util.isElement(o), false,
+             "isElement reports that {} isn't an Element");
+        o = document.createElement("div");
+        t.eq(OpenLayers.Util.isElement(o), true,
+             "isElement reports that object returned by createElement is an Element");
+        o = OpenLayers.Util.getElement("map");
+        t.eq(OpenLayers.Util.isElement(o), true,
+             "isElement reports that object returned by getElement is an Element");
+    }
     
     function test_$(t) {
         t.plan(1);
@@ -20,6 +39,14 @@
                     "getImagesLocation()" );
     }
 
+    function test_Util_IndexOf(t) {
+        t.plan( 3 );
+        var array = new Array(1, "bar");
+        t.eq(OpenLayers.Util.indexOf(array, 1), 0);
+        t.eq(OpenLayers.Util.indexOf(array, "bar"), 1);
+        t.eq(OpenLayers.Util.indexOf(array, "foo"), -1);
+    }
+
     function test_Util_Array(t) {
         t.plan( 2 );
 
@@ -70,7 +97,7 @@
 
         t.eq( div.style.position, position, "div.style.positionset correctly");    
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(div.style.borderTopWidth == s[0] && div.style.borderTopStyle == s[1], "good default popup.border")
         } else {
@@ -78,11 +105,11 @@
         }
             
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq( div.style[prop], overflow, "div.style.overflow set correctly");    
         t.eq( parseFloat(div.style.opacity), opacity, "element.style.opacity set correctly");    
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq( div.style.filter, filterString, "element.style.filter set correctly");
 
         //test defaults
@@ -103,13 +130,13 @@
 
         t.eq( div.style.position, "absolute", "div.style.positionset correctly");    
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           t.ok(div.style.borderTopWidth == '' && div.style.borderTopStyle == '', "good default popup.border")
         } else {
           t.eq( div.style.border, "", "div.style.border set correctly");    
         }
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq(div.style[prop], "", "div.style.overflow set correctly");    
         t.ok( !div.style.opacity, "element.style.opacity set correctly");    
         t.ok( !div.style.filter, "element.style.filter set correctly");
@@ -141,7 +168,7 @@
         t.eq( image.style.height, sz.h + "px", "image.style.height set correctly");    
 
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(image.style.borderTopWidth == s[0] && image.style.borderTopStyle == s[1], "good default popup.border")
         } else {
@@ -151,7 +178,7 @@
         t.eq( image.style.position, position, "image.style.position set correctly");    
         t.eq( parseFloat(image.style.opacity), opacity, "image.style.opacity set correctly");    
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq( image.style.filter, filterString, "element.style.filter set correctly");
 
         //test defaults
@@ -176,6 +203,21 @@
 
     }
 
+    function test_Util_imageLoadError(t) {
+        t.plan(2);
+
+        var img = OpenLayers.Util.createImage(null, null, null, null, null, null, null, false);
+
+        // mock up image load failure
+        img._attempts = OpenLayers.IMAGE_RELOAD_ATTEMPTS + 1;
+        OpenLayers.Util.onImageLoadError.call(img);
+        t.ok(OpenLayers.Element.hasClass(img, 'olImageLoadError'), 'broken image has class olImageLoadError');
+
+        // mock up image load success
+        OpenLayers.Util.onImageLoad.call(img);
+        t.ok(!OpenLayers.Element.hasClass(img, 'olImageLoadError'), 'good image does not have class olImageLoadError');
+    }
+
     function test_Util_applyDefaults(t) {
     
         t.plan(12);
@@ -225,7 +267,7 @@
     }
 
     function test_Util_getParameterString(t) {
-        t.plan( 4 );
+        t.plan(6);
 
         var params = { 
             'foo': "bar",
@@ -235,6 +277,8 @@
         t.eq( OpenLayers.Util.getParameterString(params), "foo=bar&chicken=1.5", "getParameterString returns correctly");    
         t.eq( OpenLayers.Util.getParameterString({'a:':'b='}), "a%3A=b%3D", "getParameterString returns correctly with non-ascii keys/values");    
         
+        t.eq(OpenLayers.Util.getParameterString({chars: "~!*()'"}), "chars=~!*()'", "~!*()' are unreserved or have no reserved purpose in a URI component");
+        
 
         // Parameters which are a list should end up being a comma-seperated
         // list of the URL encoded strings
@@ -242,9 +286,55 @@
         t.eq( OpenLayers.Util.getParameterString(params), "foo=bar%2Cbaz", "getParameterString encodes , correctly in arrays");    
         
         var params = { foo: ["bar","baz,"] };
-        t.eq( OpenLayers.Util.getParameterString(params), "foo=bar,baz%2C", "getParameterString returns with list of CSVs when given a list. ");    
+        t.eq( OpenLayers.Util.getParameterString(params), "foo=bar,baz%2C", "getParameterString returns with list of CSVs when given a list. ");
+        
+        var params = { foo: [null, undefined, 0, "", "bar"] }
+        t.eq( OpenLayers.Util.getParameterString(params), "foo=,,0,,bar", "getParameterString works fine with null values in array.");
     }
+    
+    function test_Util_urlAppend(t) {
 
+        var params = "foo=bar";
+        
+        t.plan( 7 );
+
+  // without ?        
+        var url = "http://octo.metacarta.com/cgi-bin/mapserv";
+        var str = OpenLayers.Util.urlAppend(url, params);
+        t.eq(str, url + '?' + params, "urlAppend() works for url sans ?");
+
+
+  // with ?        
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?";
+        str = OpenLayers.Util.urlAppend(url, params);
+        t.eq(str, url + params, "urlAppend() works for url with ?");
+
+  // with ?param1=5
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?param1=5";
+        str = OpenLayers.Util.urlAppend(url, params);
+        t.eq(str, url + '&' + params, "urlAppend() works for url with ?param1=5");
+  
+  // with ?param1=5&
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?param1=5&";
+        str = OpenLayers.Util.urlAppend(url, params);
+        t.eq(str, url + params, "urlAppend() works for url with ?param1=5&");
+ 
+  // with ?param1=5&param2=6
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?param1=5&param2=6";
+        str = OpenLayers.Util.urlAppend(url, params);
+        t.eq(str, url + "&" + params, "urlAppend() works for url with ?param1=5&param2=6");
+        
+  // with empty paramStr
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?param1=5"
+        str = OpenLayers.Util.urlAppend(url, "");
+        t.eq(str, url, "urlAppend() works with empty paramStr")
+
+  // with null paramStr
+        url = "http://octo.metacarta.com/cgi-bin/mapserv?param1=5"
+        str = OpenLayers.Util.urlAppend(url, null);
+        t.eq(str, url, "urlAppend() works with null paramStr")
+    }
+
     function test_Util_createAlphaImageDiv(t) {
         t.plan( 19 );
 
@@ -279,7 +369,7 @@
             filterString = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://www.openlayers.org/images/OpenLayers.trac.png', sizingMethod='crop') alpha(opacity=50)";
         } else {
             //Safari 3 returns null for this value, which is okay
-            var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+            var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         }        
         t.eq( imageDiv.style.filter, filterString, "element.style.filter set correctly");
 
@@ -295,7 +385,7 @@
         t.eq( image.style.height, sz.h + "px", "image.style.height set correctly");    
 
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(image.style.borderTopWidth == s[0] && image.style.borderTopStyle == s[1], "good default popup.border")
         } else {
@@ -347,7 +437,7 @@
         t.eq(parseFloat(element.style.opacity), opacity, 
              "element.style.opacity set correctly when opacity = " + opacity);
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq(element.style.filter, filterString, 
              "element.style.filter set correctly when opacity = " + opacity);
 
@@ -357,7 +447,7 @@
         t.eq(parseFloat(element.style.opacity), opacity, 
              "element.style.opacity not changed if the value is incorrect");
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq(element.style.filter, filterString, 
              "element.style.filter not changed if the value is incorrect");
 
@@ -367,7 +457,7 @@
         t.eq(parseFloat(element.style.opacity), opacity, 
              "element.style.opacity not changed if the value is incorrect");
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq(element.style.filter, filterString, 
              "element.style.filter not changed if the value is incorrect");
 
@@ -378,7 +468,7 @@
         t.eq(element.style.opacity, '', 
              "element.style.opacity is removed when opacity = " + opacity);
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : '';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : '';
         t.eq(element.style.filter, filterString, 
              "element.style.filter is removed when opacity = " + opacity);
     }
@@ -408,18 +498,18 @@
 
         t.eq( element.style.position, position, "element.style.position set correctly");    
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(element.style.borderTopWidth == s[0] && element.style.borderTopStyle == s[1], "good default popup.border")
         } else {
           t.ok( (element.style.border.indexOf(border) != -1), "element.style.border set correctly");
         }
         //Safari 3 separates style overflow into overflow-x and overflow-y
-        var prop = (OpenLayers.Util.getBrowserName() == 'safari') ? 'overflowX' : 'overflow';
+        var prop = (OpenLayers.BROWSER_NAME == 'safari') ? 'overflowX' : 'overflow';
         t.eq( element.style[prop], overflow, "element.style.overflow set correctly");    
         t.eq( parseFloat(element.style.opacity), opacity, "element.style.opacity set correctly");    
         //Safari 3 returns null for this value, which is okay
-        var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+        var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
         t.eq( element.style.filter, filterString, "element.style.filter set correctly");
     }
 
@@ -463,7 +553,7 @@
             t.ok( true, "skipping element test outside of Mozilla");
         } else {
             //Safari 3 returns null for this value, which is okay
-            var filterString = (OpenLayers.Util.getBrowserName() == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
+            var filterString = (OpenLayers.BROWSER_NAME == 'safari') ? null : 'alpha(opacity=' + (opacity * 100) + ')';
             t.ok( image.nodeName == "IMG", "createImage creates a valid HTMLImageElement" );
         }
         t.eq( imageDiv.style.filter, filterString, "element.style.filter set correctly");
@@ -473,7 +563,7 @@
         t.eq( image.style.height, sz.h + "px", "image.style.height set correctly");    
 
         //Safari 3 separates the border style into separate entities when reading it
-        if (OpenLayers.Util.getBrowserName() == 'safari') {
+        if (OpenLayers.BROWSER_NAME == 'safari') {
           var s = border.split(' ');
           t.ok(image.style.borderTopWidth == s[0] && image.style.borderTopStyle == s[1], "good default popup.border")
         } else {
@@ -583,7 +673,7 @@
     }
     
     function test_Util_getScaleResolutionTranslation(t) {
-        t.plan(4); 
+        t.plan(5); 
         
         var scale = 1/150000000; 
         var resolution = OpenLayers.Util.getResolutionFromScale(scale);
@@ -600,6 +690,11 @@
         scale = 150000000; 
         resolution = OpenLayers.Util.getResolutionFromScale(scale);
         t.eq(OpenLayers.Util.getScaleFromResolution(resolution), scale, "scale->resolution->scale works");
+        
+        scale = null;
+        resolution = OpenLayers.Util.getResolutionFromScale(scale);
+        t.eq(resolution, undefined, "falsey scale results in undefined resolution");
+        
     }
     
     function test_Util_getImgLocation(t) {
@@ -800,7 +895,7 @@
     }
 
     function test_Util_getParameters(t) {
-        t.plan(6);
+        t.plan(17);
 
         t.eq(OpenLayers.Util.getParameters('http://www.example.com'), {},
              "getParameters works when args = ''");
@@ -815,9 +910,62 @@
         t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar#bugssucks'),
              {'foo': 'bar'},
              "getParameters works when using a fragment identifier");
-        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar,pub,disco'),
-             {'foo': ['bar', 'pub', 'disco']},
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar%3Aone'),
+             {'foo': 'bar:one'},
+             "getParameters works with percent encoded values");
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar:one,pub,disco'),
+             {'foo': ['bar:one', 'pub', 'disco']},
              "getParameters works with a comma-separated value (parses into array)");
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar%3Aone%2Cpub%2Cdisco'),
+             {'foo': ['bar:one', 'pub', 'disco']},
+             "getParameters works with a URL encoded comma-separated values (parses into array)");
+        
+        var value = "%20";  // say you wanted to have a query string parameter value be literal "%20"
+        var encoded = encodeURIComponent(value); // this is the proper URI component encoding
+        var url = "http://example.com/path?key=" + encoded; // this is a properly encoded URL
+        var params = OpenLayers.Util.getParameters(url);
+        t.eq(params.key, value, "a properly encoded value of '%20' is properly decoded");
+
+        /**
+         * IETF RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) says spaces
+         * should be encoded as "%20".  However, the "+" is used widely to
+         * indicate a space in a URL.
+         */
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar+one'),
+             {'foo': 'bar one'},
+             "getParameters works with + instead of %20 in values");
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar%20one'),
+             {'foo': 'bar one'},
+             "getParameters works with properly encoded space character");
+        t.eq(OpenLayers.Util.getParameters('http://www.example.com?foo=bar%2Bone'),
+             {'foo': 'bar+one'},
+             "getParameters works with properly encoded + character");
+             
+        // Let's do some round tripping to make it harder to introduce regressions
+        var obj = {
+            "a key": "a value with spaces  (and +)",
+            "see%2B%2B": "C++",
+            "C++": "see%2B%2B",
+            "~%257E": "+%252B",
+            "who?": "me?",
+            "#yes": "#you",
+            "url": "http://example.com:80/?question=%3F&hash=%23&amp=&26#id"
+        };
+        var str = OpenLayers.Util.getParameterString(obj);
+        t.eq(OpenLayers.Util.getParameters("?" + str), obj, "round tripped parameters");
+        
+        // try some oddly encoded strings
+        var url = "http://example.com/?C%E9sar=C%E9sar+Ch%E1vez";
+        var obj = OpenLayers.Util.getParameters(url);
+        t.ok("César" in obj, "got proper key from C%E9sar");
+        t.eq(obj["César"], "César Chávez", "got proper value from C%E9sar+Ch%E1vez");
+        
+        // try some properly encoded strings
+        var url = "http://example.com/?C%C3%A9sar=C%C3%A9sar+Ch%C3%A1vez";
+        var obj = OpenLayers.Util.getParameters(url);
+        t.ok("César" in obj, "got proper key from C%C3%A9sar");
+        t.eq(obj["César"], "César Chávez", "got proper value from C%E9sar+Ch%E1vez");
+
     }
 
     function test_Util_getArgs(t) {

Modified: sandbox/ahocevar/playground/tests/data/geos_wkt_intersects.js
===================================================================
--- sandbox/ahocevar/playground/tests/data/geos_wkt_intersects.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/data/geos_wkt_intersects.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -357,23 +357,23 @@
 {'wkt1':'POINT (140 120)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:true},
 {'wkt1':'POINT (190 50)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(90 50,150 110,190 50,90 50),(190 50,230 110,290 50,190 50))', result:true},
 {'wkt1':'POINT (180 90)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(180 140,180 40,80 40,180 140),(180 90,210 140,310 40,230 40,180 90))', result:true},
-{'wkt1':'MULTIPOINT (20 80,110 160,20 160)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:false},
-{'wkt1':'MULTIPOINT (20 80,60 120,20 160)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (10 80,110 170,110 120)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (10 80,110 170,160 120)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (20 120,60 120,110 120,160 120,200 120)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (60 120,110 120,160 120)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (60 120,160 120,160 40,60 40)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (20 150,60 120,110 80)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (110 80,160 120,200 160)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (110 80,110 120,110 160)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (110 170,110 80)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (60 120,160 120,110 80,110 170)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (90 80,130 80)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (60 120,160 120,110 80)', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
-{'wkt1':'MULTIPOINT (40 170,40 90,130 170)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
-{'wkt1':'MULTIPOINT (90 170,280 170,190 90)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
-{'wkt1':'MULTIPOINT (190 110,150 70,230 70)', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
+{'wkt1':'MULTIPOINT ((20 80),(110 160),(20 160))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:false},
+{'wkt1':'MULTIPOINT ((20 80),(60 120),(20 160))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((10 80),(110 170),(110 120))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((10 80),(110 170),(160 120))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((20 120),(60 120),(110 120),(160 120),(200 120))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((60 120),(110 120),(160 120))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((60 120),(160 120),(160 40),(60 40))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((20 150),(60 120),(110 80))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((110 80),(160 120),(200 160))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((110 80),(110 120),(110 160))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((110 170),(110 80))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((60 120),(160 120),(110 80),(110 170))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((90 80),(130 80))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((60 120),(160 120),(110 80))', 'wkt2':'POLYGON ((60 120,60 40,160 40,160 120,60 120))', result:true},
+{'wkt1':'MULTIPOINT ((40 170),(40 90),(130 170))', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
+{'wkt1':'MULTIPOINT ((90 170),(280 170),(190 90))', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
+{'wkt1':'MULTIPOINT ((190 110),(150 70),(230 70))', 'wkt2':'POLYGON ((190 190,360 20,20 20,190 190),(280 50,100 50,190 140,280 50))', result:false},
 {'wkt1':'POINT (100 100)', 'wkt2':'MULTIPOLYGON (((20 100,20 20,100 20,100 100,20 100)),((100 180,100 100,180 100,180 180,100 180)))', result:true},
 {'wkt1':'POINT (20 100)', 'wkt2':'MULTIPOLYGON (((20 100,20 20,100 20,100 100,20 100)),((100 180,100 100,180 100,180 180,100 180)))', result:true},
 {'wkt1':'POINT (60 100)', 'wkt2':'MULTIPOLYGON (((20 100,20 20,100 20,100 100,20 100)),((100 180,100 100,180 100,180 180,100 180)))', result:true},
@@ -460,35 +460,35 @@
 {'wkt1':'POINT (110 150)', 'wkt2':'LINESTRING (20 200,110 200,110 110,20 20,200 20,110 110,110 200,200 200)', result:true},
 {'wkt1':'POINT (110 110)', 'wkt2':'LINESTRING (20 200,110 200,110 110,20 20,200 20,110 110,110 200,200 200)', result:true},
 {'wkt1':'POINT (110 200)', 'wkt2':'LINESTRING (20 200,110 200,110 110,20 20,200 20,110 110,110 200,200 200)', result:true},
-{'wkt1':'MULTIPOINT (50 250,90 220,130 190)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:false},
-{'wkt1':'MULTIPOINT (180 180,230 130,280 80)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:false},
-{'wkt1':'MULTIPOINT (50 120,90 80,130 40)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (300 280,340 240,380 200)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (230 150,260 120,290 90)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (200 190,240 150,270 110)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (160 150,190 120,220 90)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (120 190,160 150,200 110)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (90 80,160 150,340 240)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (90 80,160 150,300 150)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (90 80,160 150,240 150)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (90 80,130 120,210 150)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (130 120,210 150,340 200)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (160 150,240 150,340 210)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (160 150,300 150,340 150)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
-{'wkt1':'MULTIPOINT (160 150,240 150,340 240)', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((50 250),(90 220),(130 190))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:false},
+{'wkt1':'MULTIPOINT ((180 180),(230 130),(280 80))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:false},
+{'wkt1':'MULTIPOINT ((50 120),(90 80),(130 40))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((300 280),(340 240),(380 200))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((230 150),(260 120),(290 90))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((200 190),(240 150),(270 110))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((160 150),(190 120),(220 90))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((120 190),(160 150),(200 110))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((90 80),(160 150),(340 240))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((90 80),(160 150),(300 150))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((90 80),(160 150),(240 150))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((90 80),(130 120),(210 150))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((130 120),(210 150),(340 200))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((160 150),(240 150),(340 210))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((160 150),(300 150),(340 150))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
+{'wkt1':'MULTIPOINT ((160 150),(240 150),(340 240))', 'wkt2':'LINESTRING (90 80,160 150,300 150,340 150,340 240)', result:true},
 {'wkt1':'POINT (20 20)', 'wkt2':'POINT (20 20)', result:true},
 {'wkt1':'POINT (20 20)', 'wkt2':'POINT (40 60)', result:false},
-{'wkt1':'POINT (40 40)', 'wkt2':'MULTIPOINT (20 20,80 80,20 120)', result:false},
-{'wkt1':'POINT (20 20)', 'wkt2':'MULTIPOINT (20 20,80 80,20 120)', result:true},
-{'wkt1':'MULTIPOINT (40 40,80 60,120 100)', 'wkt2':'MULTIPOINT (40 40,80 60,120 100)', result:true},
-{'wkt1':'MULTIPOINT (40 40,80 60,120 100)', 'wkt2':'MULTIPOINT (40 40,120 100,80 60)', result:true},
-{'wkt1':'MULTIPOINT (40 40,60 100,100 60,120 120)', 'wkt2':'MULTIPOINT (20 120,60 60,100 100,140 40)', result:false},
-{'wkt1':'MULTIPOINT (20 20,80 70,140 120,200 170)', 'wkt2':'MULTIPOINT (20 20,80 70,140 120,200 170)', result:true},
-{'wkt1':'MULTIPOINT (20 20,140 120,80 70,200 170)', 'wkt2':'MULTIPOINT (80 70,20 20,200 170,140 120)', result:true},
-{'wkt1':'MULTIPOINT (20 20,80 70,140 120,200 170)', 'wkt2':'MULTIPOINT (80 70,140 120)', result:true},
-{'wkt1':'MULTIPOINT (80 70,20 20,200 170,140 120)', 'wkt2':'MULTIPOINT (140 120,80 70)', result:true},
-{'wkt1':'MULTIPOINT (80 70,20 20,200 170,140 120)', 'wkt2':'MULTIPOINT (80 170,140 120,200 80)', result:true},
-{'wkt1':'MULTIPOINT (80 70,20 20,200 170,140 120)', 'wkt2':'MULTIPOINT (80 170,140 120,200 80,80 70)', result:true},
+{'wkt1':'POINT (40 40)', 'wkt2':'MULTIPOINT ((20 20),(80 80),(20 120))', result:false},
+{'wkt1':'POINT (20 20)', 'wkt2':'MULTIPOINT ((20 20),(80 80),(20 120))', result:true},
+{'wkt1':'MULTIPOINT ((40 40),(80 60),(120 100))', 'wkt2':'MULTIPOINT ((40 40),(80 60),(120 100))', result:true},
+{'wkt1':'MULTIPOINT ((40 40),(80 60),(120 100))', 'wkt2':'MULTIPOINT ((40 40),(120 100),(80 60))', result:true},
+{'wkt1':'MULTIPOINT ((40 40),(60 100),(100 60),(120 120))', 'wkt2':'MULTIPOINT ((20 120),(60 60),(100 100),(140 40))', result:false},
+{'wkt1':'MULTIPOINT ((20 20),(80 70),(140 120),(200 170))', 'wkt2':'MULTIPOINT ((20 20),80 70),(140 120),(200 170))', result:true},
+{'wkt1':'MULTIPOINT ((20 20),(140 120),(80 70),(200 170))', 'wkt2':'MULTIPOINT ((80 70),20 20),(200 170),(140 120))', result:true},
+{'wkt1':'MULTIPOINT ((20 20),(80 70),(140 120),(200 170))', 'wkt2':'MULTIPOINT ((80 70),(140 120))', result:true},
+{'wkt1':'MULTIPOINT ((80 70),(20 20),(200 170),(140 120))', 'wkt2':'MULTIPOINT ((140 120),(80 70))', result:true},
+{'wkt1':'MULTIPOINT ((80 70),(20 20),(200 170),(140 120))', 'wkt2':'MULTIPOINT ((80 170),(140 120),(200 80))', result:true},
+{'wkt1':'MULTIPOINT ((80 70),(20 20),(200 170),(140 120))', 'wkt2':'MULTIPOINT ((80 170),(140 120),(200 80),(80 70))', result:true},
 {'wkt1':'POLYGON((-8239529.462853361 4980952.065110421,-8224242.057199065 4980952.065110421,-8224242.057199064 4988844.188279452,-8239529.462853361 4988844.188279452,-8239529.462853361 4980952.065110421))', 'wkt2':'POINT(-8225445.94039435  4982695.78481786)', result:true},
 {'wkt1':'POLYGON((-8239529.462853361 4980952.065110421,-8224242.057199065 4980952.065110421,-8224242.057199064 4988844.188279452,-8239529.462853361 4988844.188279452,-8239529.462853361 4980952.065110421))', 'wkt2':'POINT(-8224242.0571985  4982695.78481786)', result:false},
 {'wkt1':'POLYGON((-8239529.462853361 4980952.065110421,-8224242.057199065 4980952.065110421,-8224242.057199064 4988844.188279452,-8239529.462853361 4988844.188279452,-8239529.462853361 4980952.065110421))', 'wkt2':'POINT(-8224242.0571995  4982695.78481786)', result:true}

Modified: sandbox/ahocevar/playground/tests/list-tests.html
===================================================================
--- sandbox/ahocevar/playground/tests/list-tests.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/list-tests.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -15,6 +15,7 @@
     <li>Control/DragPan.html</li>
     <li>Control/DrawFeature.html</li>
     <li>Control/GetFeature.html</li>
+    <li>Control/Graticule.html</li>
     <li>Control/KeyboardDefaults.html</li>
     <li>Control/LayerSwitcher.html</li>
     <li>Control/Measure.html</li>
@@ -34,7 +35,11 @@
     <li>Control/SelectFeature.html</li>
     <li>Control/Snapping.html</li>
     <li>Control/Split.html</li>
+    <li>Control/TransformFeature.html</li>
     <li>Control/WMSGetFeatureInfo.html</li>
+    <li>Control/WMTSGetFeatureInfo.html</li>
+    <li>Control/PanPanel.html</li>
+    <li>Control/SLDSelect.html</li>
     <li>Events.html</li>
     <li>Extras.html</li>
     <li>Feature.html</li>
@@ -45,6 +50,7 @@
     <li>Filter/Logical.html</li>
     <li>Filter/Spatial.html</li>
     <li>Format.html</li>
+    <li>Format/Atom.html</li>
     <li>Format/ArcXML.html</li>
     <li>Format/ArcXML/Features.html</li>
     <li>Format/GeoJSON.html</li>
@@ -77,8 +83,19 @@
     <li>Format/WMC/v1.html</li>
     <li>Format/WMSCapabilities.html</li>
     <li>Format/WMSCapabilities/v1_1_1.html</li>
+    <li>Format/WMSCapabilities/v1_3_0.html</li>
     <li>Format/WMSDescribeLayer.html</li>
     <li>Format/WMSGetFeatureInfo.html</li>
+    <li>Format/WMTSCapabilities.html</li>
+    <li>Format/WMTSCapabilities/v1_0_0.html</li>
+    <li>Format/CSWGetDomain.html</li>
+    <li>Format/CSWGetDomain/v2_0_2.html</li>
+    <li>Format/CSWGetRecords.html</li>
+    <li>Format/CSWGetRecords/v2_0_2.html</li>
+    <li>Format/SOSCapabilities/v1_0_0.html</li>
+    <li>Format/SOSGetObservation.html</li>
+    <li>Format/SOSGetFeatureOfInterest.html</li>
+    <li>Format/OWSContext/v0_3_1.html</li>
     <li>Format/XML.html</li>
     <li>Geometry.html</li>
     <li>Geometry/Collection.html</li>
@@ -113,6 +130,7 @@
     <li>Layer/GeoRSS.html</li>
     <li>Layer/GML.html</li>
     <li>Layer/Google.html</li>
+    <li>Layer/Google/v3.html</li>
     <li>Layer/Grid.html</li>
     <li>Layer/HTTPRequest.html</li>
     <li>Layer/Image.html</li>
@@ -120,6 +138,7 @@
     <li>Layer/MapGuide.html</li>
     <li>Layer/MapServer.html</li>
     <li>Layer/Markers.html</li>
+    <li>Layer/MultiMap.html</li>
     <li>Layer/PointTrack.html</li>
     <li>Layer/SphericalMercator.html</li>
     <li>Layer/Text.html</li>
@@ -129,13 +148,18 @@
     <li>Layer/Vector/RootContainer.html</li>
     <li>Layer/WFS.html</li>
     <li>Layer/WMS.html</li>
+    <li>Layer/WMS/Post.html</li>
+    <li>Layer/WMTS.html</li>
     <li>Layer/WrapDateLine.html</li>
     <li>Layer/XYZ.html</li>
     <li>Layer/Yahoo.html</li>
     <li>Map.html</li>
     <li>Marker.html</li>
     <li>Marker/Box.html</li>
-    <li>OpenLayers.html</li>
+    <li>OpenLayers1.html</li>
+    <li>OpenLayers2.html</li>
+    <li>OpenLayers3.html</li>
+    <li>OpenLayers4.html</li>
     <li>Popup.html</li>
     <li>Popup/Anchored.html</li>
     <li>Popup/AnchoredBubble.html</li>
@@ -146,6 +170,7 @@
     <li>Protocol/SQL.html</li>
     <li>Protocol/SQL/Gears.html</li>
     <li>Protocol/WFS.html</li>
+    <li>Protocol/SOS.html</li>
     <li>Renderer.html</li>
     <li>Renderer/Canvas.html</li>
     <li>Renderer/Elements.html</li>
@@ -157,13 +182,23 @@
     <li>Strategy.html</li>
     <li>Strategy/BBOX.html</li>
     <li>Strategy/Cluster.html</li>
+    <li>Strategy/Filter.html</li>
     <li>Strategy/Fixed.html</li>
     <li>Strategy/Paging.html</li>
     <li>Strategy/Save.html</li>
+    <li>Strategy/Refresh.html</li>
     <li>Style.html</li>
+    <li>Style2.html</li>
     <li>StyleMap.html</li>
+    <li>Symbolizer.html</li>
+    <li>Symbolizer/Line.html</li>
+    <li>Symbolizer/Point.html</li>
+    <li>Symbolizer/Polygon.html</li>
+    <li>Symbolizer/Raster.html</li>
+    <li>Symbolizer/Text.html</li>
     <li>Tile.html</li>
     <li>Tile/Image.html</li>
+    <li>Tile/Image/IFrame.html</li>
     <li>Tile/WFS.html</li>
     <li>Tween.html</li>
     <li>Util.html</li>

Copied: sandbox/ahocevar/playground/tests/manual/arcims-2117.html (from rev 10919, trunk/openlayers/tests/manual/arcims-2117.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/arcims-2117.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/arcims-2117.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,103 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>ArcIMS Test Ticket #2117</title>
+    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="../../examples/style.css" type="text/css" />
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var lon = 0;
+        var lat = 0;
+        var zoom = 1;
+        var map, layer;
+
+        function init(){
+            OpenLayers.ProxyHost = "../../examples/proxy.cgi?url=";
+            
+            map = new OpenLayers.Map( 'map' );
+            
+            var options = {
+              serviceName: "OpenLayers_Sample",
+              async: true,
+							layers: [{
+								id:1,
+								visible:'true',
+								/*query:{
+									where: '1=1',
+									spatialfilter: true
+								},*/
+								renderer:{
+									type: 'valuemaplabel',
+									lookupfield: 'FIPS_ID',
+									labelfield: 'FIPS_CNTRY',
+									exacts:[{
+										value: '227',
+										symbol: {
+											type: 'text',
+											antialiasing: 'true',
+											interval: 6,
+											blockout: '255,255,255',
+											font: 'Arial',
+											fontcolor: '0,0,0',
+											fontsize: 11,
+											transparency: 0.7
+										}
+									},{
+										value: '150',
+										symbol: {
+											type: 'text',
+											antialiasing: 'true',
+											interval: 6,
+											blockout: '255,255,255',
+											font: 'Arial',
+											fontcolor: '0,0,0',
+											fontsize: 11,
+											transparency: 0.7
+										}
+									},{
+										value: '75',
+										symbol: {
+											type: 'text',
+											antialiasing: 'true',
+											interval: 6,
+											blockout: '255,255,255',
+											font: 'Arial',
+											fontcolor: '0,0,0',
+											fontsize: 11,
+											transparency: 0.7
+										}
+									}]
+								}
+							}]
+            };
+            
+            layer = new OpenLayers.Layer.ArcIMS( "Global Sample Map",
+                    "http://sample.avencia.com/servlet/com.esri.esrimap.Esrimap", options );
+            map.addLayer(layer);
+
+            map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
+            map.addControl( new OpenLayers.Control.LayerSwitcher() );
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">ArcIMS Test Ticket #2117</h1>
+
+    <div id="tags">
+    </div>
+    <p id="shortdesc">
+        <a href="http://trac.openlayers.org/ticket/2117">Testing ticket #2117</a>
+    </p>
+
+    <div id="map" class="smallmap"></div>
+
+    <div id="docs">
+        This is an example of a bug in the ArcXML format writer.
+         If you don't see a map, it's broken.
+    </div>
+
+  </body>
+</html>
+
+
+
+

Modified: sandbox/ahocevar/playground/tests/manual/clip-features-svg.html
===================================================================
--- sandbox/ahocevar/playground/tests/manual/clip-features-svg.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/clip-features-svg.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -4,21 +4,26 @@
 href="../../theme/default/style.css"
 rel="stylesheet" type="text/css">
 <style>
-       #map {
-             width: 512px;
-             height: 512px;
-             border: 1px solid #4B3624;
-             background: White;
-       }
+        #map {
+            width: 512px;
+            height: 512px;
+            border: 1px solid #4B3624;
+            background: White;
+        }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
+
        .olControlAttribution { bottom: 0px!important }
 </style>
 <script src="../../lib/OpenLayers.js"
 type="text/javascript"></script>
 <script type="text/javascript">var map;
 
-     // avoid pink tiles
-     OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
-     OpenLayers.Util.onImageLoadErrorColor = "transparent";
+      // increase reload attempts 
+      OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
 
       var vectorLayer;
       var markerLayer, boxes, newPoint;
@@ -120,4 +125,4 @@
     <button onClick="zoomToScale(7);">Zoom 7</button>
     <button onClick="zoomToScale(8);">Zoom 8</button>
 </body>
-</html>
\ No newline at end of file
+</html>

Copied: sandbox/ahocevar/playground/tests/manual/geodesic.html (from rev 10919, trunk/openlayers/tests/manual/geodesic.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/geodesic.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/geodesic.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,160 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
+    <style type="text/css">
+        #controlToggle li {
+            list-style: none;
+        }
+        #options {
+            position: relative;
+            width: 512px;
+        }
+        #output {
+            float: right;
+        }
+
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
+    </style>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, measureControls;
+        function init(){
+            map = new OpenLayers.Map('map');
+            
+            var wmsLayer = new OpenLayers.Layer.OSM(); 
+
+            map.addLayers([wmsLayer]);
+            map.setCenter(new OpenLayers.LonLat(0,0), 5);
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+            map.addControl(new OpenLayers.Control.MousePosition());
+            map.addControl(new OpenLayers.Control.ScaleLine({geodesic: true}))
+            
+            // style the sketch fancy
+            var sketchSymbolizers = {
+                "Point": {
+                    pointRadius: 4,
+                    graphicName: "square",
+                    fillColor: "white",
+                    fillOpacity: 1,
+                    strokeWidth: 1,
+                    strokeOpacity: 1,
+                    strokeColor: "#333333"
+                },
+                "Line": {
+                    strokeWidth: 3,
+                    strokeOpacity: 1,
+                    strokeColor: "#666666",
+                    strokeDashstyle: "dash"
+                },
+                "Polygon": {
+                    strokeWidth: 2,
+                    strokeOpacity: 1,
+                    strokeColor: "#666666",
+                    fillColor: "white",
+                    fillOpacity: 0.3
+                }
+            };
+            var style = new OpenLayers.Style();
+            style.addRules([
+                new OpenLayers.Rule({symbolizer: sketchSymbolizers})
+            ]);
+            var styleMap = new OpenLayers.StyleMap({"default": style});
+            
+            measureControls = {
+                line: new OpenLayers.Control.Measure(
+                    OpenLayers.Handler.Path, {
+                        geodesic: true,
+                        persist: true,
+                        handlerOptions: {
+                            layerOptions: {styleMap: styleMap}
+                        }
+                    }
+                ),
+                polygon: new OpenLayers.Control.Measure(
+                    OpenLayers.Handler.Polygon, {
+                        geodesic: true,
+                        persist: true,
+                        handlerOptions: {
+                            layerOptions: {styleMap: styleMap}
+                        }
+                    }
+                )
+            };
+            
+            var control;
+            for(var key in measureControls) {
+                control = measureControls[key];
+                control.events.on({
+                    "measure": handleMeasurements,
+                    "measurepartial": handleMeasurements
+                });
+                map.addControl(control);
+            }
+            
+            map.setCenter(new OpenLayers.LonLat(0, 0), 3);
+            
+            document.getElementById('noneToggle').checked = true;
+        }
+        
+        function handleMeasurements(event) {
+            var geometry = event.geometry;
+            var units = event.units;
+            var order = event.order;
+            var measure = event.measure;
+            var element = document.getElementById('output');
+            var out = "";
+            if(order == 1) {
+                out += "measure: " + measure.toFixed(3) + " " + units;
+            } else {
+                out += "measure: " + measure.toFixed(3) + " " + units + "<sup>2</" + "sup>";
+            }
+            element.innerHTML = out;
+        }
+
+        function toggleControl(element) {
+            for(key in measureControls) {
+                var control = measureControls[key];
+                if(element.value == key && element.checked) {
+                    control.activate();
+                } else {
+                    control.deactivate();
+                }
+            }
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">OpenLayers Geodesic Measurement & ScaleLine</h1>
+    <p id="shortdesc">
+        Tests geodesic measurement of distances and areas against a geodesic ScaleLine.
+    </p>
+    <div id="map" style="width: 512px; height: 300px;"></div>
+    <div id="options">
+        <div id="output">
+        </div>
+        <ul id="controlToggle">
+            <li>
+                <input type="radio" name="type" value="none" id="noneToggle"
+                       onclick="toggleControl(this);" checked="checked" />
+                <label for="noneToggle">navigate</label>
+            </li>
+            <li>
+                <input type="radio" name="type" value="line" id="lineToggle" onclick="toggleControl(this);" />
+                <label for="lineToggle">measure distance</label>
+            </li>
+            <li>
+                <input type="radio" name="type" value="polygon" id="polygonToggle" onclick="toggleControl(this);" />
+                <label for="polygonToggle">measure area</label>
+            </li>
+        </ul>
+    </div>
+    <p>Zoom in so the ScaleLine shows units in the range of 10-100 km. Measure
+    the length of the ScaleLine. The result should be approximately the same
+    as the distance printed on the ScaleLine.</p>
+    <p>Zoom out so the ScaleLine shows units in the range of 100-500 km. Drag
+    the map to the South or North and see how the ScaleLine length changes.</p>
+  </body>
+</html>

Modified: sandbox/ahocevar/playground/tests/manual/google-panning.html
===================================================================
--- sandbox/ahocevar/playground/tests/manual/google-panning.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/google-panning.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -24,6 +24,10 @@
             height: 255px;
         }
 
+        /* avoid pink tiles */
+        .olImageLoadError {
+            background-color: transparent !important;
+        }
 
     </style>
 
@@ -33,8 +37,9 @@
     <script type="text/javascript">
  
         var evenmap, oddmap;
+
+        // increase reload attempts 
         OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
 
         function init(){
             evenmap = new OpenLayers.Map('evenmap');

Copied: sandbox/ahocevar/playground/tests/manual/google-resize.html (from rev 10919, trunk/openlayers/tests/manual/google-resize.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/google-resize.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/google-resize.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,55 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>OpenLayers Google Layer Example</title>
+    <link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="../../examples/style.css" type="text/css" />
+    <!-- this gmaps key generated for http://openlayers.org/dev/ -->
+    <script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
+    <script src="../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map;
+
+        function init() {
+            var mapOptions = {
+                projection: "EPSG:900913",
+                displayProjection: new OpenLayers.Projection("EPSG:4326"), //Pour afficher les coord lat long
+                units: "m",
+                maxResolution: 156543.0339,
+                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
+                controls: [new OpenLayers.Control.LayerSwitcher()],
+                numZoomLevels: 20
+            };
+            map = new OpenLayers.Map('map', mapOptions);
+
+            var dummy = new OpenLayers.Layer(
+                "Dummy",
+                {isBaseLayer: true}
+            );
+            var gmap = new OpenLayers.Layer.Google(
+                "Google Streets", {sphericalMercator: true}
+            );
+
+            map.addLayers([dummy, gmap]);
+
+            map.setCenter(new OpenLayers.LonLat(-7712190.388467473, 6567469.498697457), 6);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Google Layer Resize Issue</h1>
+
+    <div id="tags"></div>
+
+    <p id="shortdesc">
+        <ol>
+            <li>Click
+                <button onclick="var m = document.getElementById('map').style; m.height = '400px'; m.width = '800px'; map.updateSize(); return false;">Resize</button></li>
+            <li>Open the LayerSwitcher and switch to Google Streets</li>
+            <li>Confirm that the whole map area is populated with tiles</li>
+        </ol>
+    </p>
+
+    <div id="map" style="width: 200px; height: 200px"></div>
+
+  </body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html
===================================================================
--- trunk/openlayers/tests/manual/memory/Marker-2258.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,60 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>Memory Test - Layer.Markers / Marker</title>
-    <style type="text/css">
-        body {
-            font-size: 0.8em;
-        }
-        p {
-            padding-top: 1em;
-        }
-        #map {
-            width: 256px;
-            height: 256px;
-            border: 1px solid black;
-        }
-    </style>
-
-    <script src="../../../lib/Firebug/firebug.js"></script>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map, layer, marker;
-        
-        function init(){
-            map = new OpenLayers.Map('map');
-            map.addLayer(new OpenLayers.Layer.WMS( "OpenLayers WMS", 
-                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} ));
-            map.setCenter(new OpenLayers.LonLat(0, 0), 0);
-            
-            layer = new OpenLayers.Layer.Markers( "Markers" );
-            map.addLayer(layer);
-            
-            marker = new OpenLayers.Marker(new OpenLayers.LonLat(0,0));
-            layer.addMarker(marker);
-            
-            window.setTimeout(function() {
-                layer.removeMarker(marker);
-                layer.addMarker(marker);
-                
-                // people SHOULD call marker.destroy(). But if they don't
-                // we leak memory.
-                //marker.destroy();
-                
-                window.alert("Setup - hit STOP in the leak detector now");
-            }, 100);
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">Memory Test - Layer.Markers / Marker</h1>
-    <pre id="status"></pre>
-    <div id="map"></div>
-    <p>
-    This test is a memory leak test for usage of Layer.Markers / Marker.
-    </p>
-    <p>
-    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
-    and watch it identify a leak unless this is fixed.
-    </p>
-  </body>
-</html>

Copied: sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html (from rev 10919, trunk/openlayers/tests/manual/memory/Marker-2258.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/memory/Marker-2258.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,60 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Memory Test - Layer.Markers / Marker</title>
+    <style type="text/css">
+        body {
+            font-size: 0.8em;
+        }
+        p {
+            padding-top: 1em;
+        }
+        #map {
+            width: 256px;
+            height: 256px;
+            border: 1px solid black;
+        }
+    </style>
+
+    <script src="../../../lib/Firebug/firebug.js"></script>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, layer, marker;
+        
+        function init(){
+            map = new OpenLayers.Map('map');
+            map.addLayer(new OpenLayers.Layer.WMS( "OpenLayers WMS", 
+                "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} ));
+            map.setCenter(new OpenLayers.LonLat(0, 0), 0);
+            
+            layer = new OpenLayers.Layer.Markers( "Markers" );
+            map.addLayer(layer);
+            
+            marker = new OpenLayers.Marker(new OpenLayers.LonLat(0,0));
+            layer.addMarker(marker);
+            
+            window.setTimeout(function() {
+                layer.removeMarker(marker);
+                layer.addMarker(marker);
+                
+                // people SHOULD call marker.destroy(). But if they don't
+                // we leak memory.
+                //marker.destroy();
+                
+                window.alert("Setup - hit STOP in the leak detector now");
+            }, 100);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Memory Test - Layer.Markers / Marker</h1>
+    <pre id="status"></pre>
+    <div id="map"></div>
+    <p>
+    This test is a memory leak test for usage of Layer.Markers / Marker.
+    </p>
+    <p>
+    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
+    and watch it identify a leak unless this is fixed.
+    </p>
+  </body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html
===================================================================
--- trunk/openlayers/tests/manual/memory/PanZoom-2323.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,41 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>Memory Test - PanZoom.getSlideFactor</title>
-    <style type="text/css">
-        body {
-            font-size: 0.8em;
-        }
-        p {
-            padding-top: 1em;
-        }
-        #map {
-            width: 256px;
-            height: 256px;
-            border: 1px solid black;
-        }
-    </style>
-
-    <script src="../../../lib/Firebug/firebug.js"></script>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map;
-        var layer;
-        
-        function init(){
-            map = new OpenLayers.Map('map');
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">Memory Test - PanZoom.getSlideFactor</h1>
-    <pre id="status"></pre>
-    <div id="map"></div>
-    <p>
-    This test is a memory leak test for: PanZoom.getSlideFactor.
-    </p>
-    <p>
-    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
-    and watch it identify a leak unless this is fixed.
-    </p>
-  </body>
-</html>

Copied: sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html (from rev 10919, trunk/openlayers/tests/manual/memory/PanZoom-2323.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/memory/PanZoom-2323.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,41 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Memory Test - PanZoom.getSlideFactor</title>
+    <style type="text/css">
+        body {
+            font-size: 0.8em;
+        }
+        p {
+            padding-top: 1em;
+        }
+        #map {
+            width: 256px;
+            height: 256px;
+            border: 1px solid black;
+        }
+    </style>
+
+    <script src="../../../lib/Firebug/firebug.js"></script>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map;
+        var layer;
+        
+        function init(){
+            map = new OpenLayers.Map('map');
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Memory Test - PanZoom.getSlideFactor</h1>
+    <pre id="status"></pre>
+    <div id="map"></div>
+    <p>
+    This test is a memory leak test for: PanZoom.getSlideFactor.
+    </p>
+    <p>
+    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
+    and watch it identify a leak unless this is fixed.
+    </p>
+  </body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html
===================================================================
--- trunk/openlayers/tests/manual/memory/RemoveChild-2170.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,56 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>Memory Test - DOMNode.removeChild</title>
-    <style type="text/css">
-        body {
-            font-size: 0.8em;
-        }
-        p {
-            padding-top: 1em;
-        }
-        #map {
-            width: 512px;
-            height: 512px;
-            border: 1px solid black;
-        }
-    </style>
-
-    <script src="../../../lib/Firebug/firebug.js"></script>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map, layer;
-        
-        function tearDown() {
-            layer.events.unregister("loadend", layer, tearDown);
-            window.setTimeout(function() {
-                map.removeLayer(layer);
-                //map.addLayer(layer);
-                layer.destroy();
-                window.alert("Setup - hit STOP in the leak detector now");
-            }, 100);
-        }
-        
-        function init(){
-            map = new OpenLayers.Map( 'map', {maxResolution:1.40625/2} );
-            layer = new OpenLayers.Layer.TMS( "TMS",
-                    "http://labs.metacarta.com/wms-c/Basic.py/", {layername: 'basic', type:'png'} );
-            map.addLayer(layer);
-            map.setCenter(new OpenLayers.LonLat(5, 40), 5);
-            
-            layer.events.register("loadend", layer, tearDown);
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">Memory Test - DOMNode.removeChild</h1>
-    <pre id="status"></pre>
-    <div id="map"></div>
-    <p>
-    This test is a memory leak test for usage of DOMNode.removeChild
-    </p>
-    <p>
-    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
-    and watch it identify a leak unless this is fixed.
-    </p>
-  </body>
-</html>

Copied: sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html (from rev 10919, trunk/openlayers/tests/manual/memory/RemoveChild-2170.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/memory/RemoveChild-2170.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,56 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Memory Test - DOMNode.removeChild</title>
+    <style type="text/css">
+        body {
+            font-size: 0.8em;
+        }
+        p {
+            padding-top: 1em;
+        }
+        #map {
+            width: 512px;
+            height: 512px;
+            border: 1px solid black;
+        }
+    </style>
+
+    <script src="../../../lib/Firebug/firebug.js"></script>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map, layer;
+        
+        function tearDown() {
+            layer.events.unregister("loadend", layer, tearDown);
+            window.setTimeout(function() {
+                map.removeLayer(layer);
+                //map.addLayer(layer);
+                layer.destroy();
+                window.alert("Setup - hit STOP in the leak detector now");
+            }, 100);
+        }
+        
+        function init(){
+            map = new OpenLayers.Map( 'map', {maxResolution:1.40625/2} );
+            layer = new OpenLayers.Layer.TMS( "TMS",
+                    "http://labs.metacarta.com/wms-c/Basic.py/", {layername: 'basic', type:'png'} );
+            map.addLayer(layer);
+            map.setCenter(new OpenLayers.LonLat(5, 40), 5);
+            
+            layer.events.register("loadend", layer, tearDown);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Memory Test - DOMNode.removeChild</h1>
+    <pre id="status"></pre>
+    <div id="map"></div>
+    <p>
+    This test is a memory leak test for usage of DOMNode.removeChild
+    </p>
+    <p>
+    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
+    and watch it identify a leak unless this is fixed.
+    </p>
+  </body>
+</html>

Deleted: sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html
===================================================================
--- trunk/openlayers/tests/manual/memory/VML-2170.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,49 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>Memory Test - Renderer.VML - onselectstart</title>
-    <style type="text/css">
-        body {
-            font-size: 0.8em;
-        }
-        p {
-            padding-top: 1em;
-        }
-        #map {
-            width: 256px;
-            height: 256px;
-            border: 1px solid black;
-        }
-    </style>
-
-    <script src="../../../lib/Firebug/firebug.js"></script>
-    <script src="../../../lib/OpenLayers.js"></script>
-    <script type="text/javascript">
-        var map;
-        var layer;
-        
-        function init(){
-            map = new OpenLayers.Map('map');
-            
-            layer = new OpenLayers.Layer.Vector("Test-VML", {renderers:['VML']});
-            map.addLayers([layer]);
-            
-            window.setTimeout(function() {
-                layer.redraw();
-                window.alert("Setup - hit STOP in the leak detector now");
-            }, 100);
-        }
-    </script>
-  </head>
-  <body onload="init()">
-    <h1 id="title">Memory Test - Renderer.VML - onselectstart</h1>
-    <pre id="status"></pre>
-    <div id="map"></div>
-    <p>
-    This test is a memory leak test for usage of "onselectstart" event handler in Renderer.VML
-    </p>
-    <p>
-    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
-    and watch it identify a leak unless this is fixed.
-    </p>
-  </body>
-</html>

Copied: sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html (from rev 10919, trunk/openlayers/tests/manual/memory/VML-2170.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/memory/VML-2170.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,49 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Memory Test - Renderer.VML - onselectstart</title>
+    <style type="text/css">
+        body {
+            font-size: 0.8em;
+        }
+        p {
+            padding-top: 1em;
+        }
+        #map {
+            width: 256px;
+            height: 256px;
+            border: 1px solid black;
+        }
+    </style>
+
+    <script src="../../../lib/Firebug/firebug.js"></script>
+    <script src="../../../lib/OpenLayers.js"></script>
+    <script type="text/javascript">
+        var map;
+        var layer;
+        
+        function init(){
+            map = new OpenLayers.Map('map');
+            
+            layer = new OpenLayers.Layer.Vector("Test-VML", {renderers:['VML']});
+            map.addLayers([layer]);
+            
+            window.setTimeout(function() {
+                layer.redraw();
+                window.alert("Setup - hit STOP in the leak detector now");
+            }, 100);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Memory Test - Renderer.VML - onselectstart</h1>
+    <pre id="status"></pre>
+    <div id="map"></div>
+    <p>
+    This test is a memory leak test for usage of "onselectstart" event handler in Renderer.VML
+    </p>
+    <p>
+    Run this test in IE6/7 with <a href="http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx">JavaScript Memory Leak Detector v2</a>
+    and watch it identify a leak unless this is fixed.
+    </p>
+  </body>
+</html>

Copied: sandbox/ahocevar/playground/tests/manual/multiple-google-layers.html (from rev 10919, trunk/openlayers/tests/manual/multiple-google-layers.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/multiple-google-layers.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/multiple-google-layers.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,135 @@
+<html>
+    <head>
+        <title>Multiple Google Layers Acceptance Test</title>
+        <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ"></script> 
+        <script src="../../lib/OpenLayers.js"></script>
+        <link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="../../theme/default/google.css" type="text/css" />
+        <style>
+            .col {
+                position: relative;
+                width: 50%;
+            }
+            #col1 {
+                float: left;
+            }
+            #col2 {
+                float: right;
+            }
+            .map {
+                position: relative;
+                height: 300px;
+            }
+            .wrap {
+                position: relative;
+                padding: 10px;
+            }
+            ul {
+                padding: 0;
+            }
+            ul li {
+                list-style: none;
+            }
+            p.clear {
+                clear: both;
+            }
+        </style>
+    </head>
+    <body>
+        <div id="col1" class="col">
+            <div class="wrap">
+                <div id="map1" class="map"></div>
+                layers for map1
+                <ul>
+                    <li><input type="checkbox" checked="checked" name="streets1" id="streets1"><label for="streets1">streets</label></li>
+                    <li><input type="checkbox" checked="checked" name="sat1" id="sat1"><label for="sat1">imagery</label></li>
+                    <li><input type="checkbox" checked="checked" name="topo1" id="topo1"><label for="topo1">topography</label></li>
+                </ul>
+            </div>
+        </div>
+        <div id="col2" class="col">
+            <div class="wrap">
+                <div id="map2" class="map"></div>
+                layers for map2
+                <ul>
+                    <li><input type="checkbox" name="streets2" id="streets2"><label for="streets2">streets</label></li>
+                    <li><input type="checkbox" name="sat2" id="sat2"><label for="sat2">imagery</label></li>
+                    <li><input type="checkbox" name="topo2" id="topo2"><label for="topo2">topography</label></li>
+                </ul>
+            </div>
+        </div>
+        <p class="clear">
+            This example is used to confirm that resizable maps with multiple
+            Google layers work properly.  Click the checkboxes to add/remove
+            layers from the maps.  Use the layer switcher to change the map's
+            base layer.  You should be able to confirm the following:
+            <ol>
+                <li>Adding and removing layers doesn't raise any errors
+                (regardless of how many times the same layer is added/removed).</li>
+                <li>The Google "Powered By" link is always visible and clickable
+                when a Google layer is displayed.</li>
+                <li>The Google "Terms of Use" link is always visible and clickable
+                when a Google layer is displayed.</li>
+                <li>Resizing a map (by resizing the browser window) and then
+                changing base layer works well.  That is, the center & scale are
+                preserved and all tiles are well aligned.</li>
+                <li>Setting the base layer to the "Dummy Layer" hides all other
+                Google base layers, "Powered By" link, and "Terms of Use" link.</li>
+            </ol>
+        </p>
+        <script>
+        
+            var map1 = new OpenLayers.Map("map1");
+            var streets1 = new OpenLayers.Layer.Google("Streets", {
+                type: G_NORMAL_MAP
+            });
+            var sat1 = new OpenLayers.Layer.Google("Imagery", {
+                type: G_SATELLITE_MAP
+            });
+            var topo1 = new OpenLayers.Layer.Google("Topography", {
+                type: G_PHYSICAL_MAP
+            });
+            var dummy1 = new OpenLayers.Layer("Dummy Layer", {
+                isBaseLayer: true
+            });
+            map1.addLayers([streets1, sat1, topo1, dummy1]);
+            map1.addControl(new OpenLayers.Control.LayerSwitcher);
+            map1.zoomToMaxExtent();
+        
+            var map2 = new OpenLayers.Map("map2");
+            var streets2 = new OpenLayers.Layer.Google("Streets", {
+                type: G_NORMAL_MAP
+            });
+            var sat2 = new OpenLayers.Layer.Google("Imagery", {
+                type: G_SATELLITE_MAP
+            });
+            var topo2 = new OpenLayers.Layer.Google("Topography", {
+                type: G_PHYSICAL_MAP
+            });
+            var dummy2 = new OpenLayers.Layer("Dummy Layer", {
+                isBaseLayer: true
+            });
+            map2.addLayer(dummy2);
+            map2.addControl(new OpenLayers.Control.LayerSwitcher);
+            map2.zoomToMaxExtent();
+            
+            // add behavior to checkboxes
+            var check, inputs = document.getElementsByTagName("input");
+            for (var i=0, len=inputs.length; i<len; ++i) {
+                check = inputs[i];
+                check.onclick = function() {
+                    var name = this.name;
+                    var num = name.match(/\d$/)[0];
+                    var layer = window[name];
+                    var map = window["map" + num];
+                    if (this.checked) {
+                        map.addLayer(layer);
+                    } else {
+                        map.removeLayer(layer);
+                    }
+                }
+            }
+
+        </script>
+    </body>
+</html>
\ No newline at end of file

Copied: sandbox/ahocevar/playground/tests/manual/page-position.html (from rev 10919, trunk/openlayers/tests/manual/page-position.html)
===================================================================
--- sandbox/ahocevar/playground/tests/manual/page-position.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/manual/page-position.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title>Page Position Test</title>
+        
+        <link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
+        <link rel="stylesheet" href="../../examples/style.css" type="text/css" />
+        <style type="text/css">
+            #mapwrap {
+                border: 10px solid red;
+                width: 532px;
+                height: 276px;
+            }
+            #map {
+                position: absolute;
+                border: 10px solid #ccc;
+                width: 512px;
+                height: 256px;
+            }
+            #controlToggle li {
+                list-style: none;
+            }
+            p {
+                width: 512px;
+            }
+            #scrollspace {
+                height: 500px;
+            }
+        </style>
+        <script src="../../lib/OpenLayers.js"></script>
+        <script type="text/javascript">
+            var map, drawControls;
+            function init(){
+                map = new OpenLayers.Map('map');
+
+                var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'});
+
+                var lineLayer = new OpenLayers.Layer.Vector("Line Layer");
+
+                map.addLayers([wmsLayer, lineLayer]);
+                map.addControl(new OpenLayers.Control.LayerSwitcher());
+                map.addControl(new OpenLayers.Control.MousePosition());
+
+                drawControl = new OpenLayers.Control.DrawFeature(lineLayer,
+                                OpenLayers.Handler.Path);
+
+                map.addControl(drawControl);
+
+                map.setCenter(new OpenLayers.LonLat(0, 0), 3);
+
+                document.getElementById('noneToggle').checked = true;
+            }
+
+            function toggleControl(element) {
+                var control = drawControl;
+                if(element.value == "draw" && element.checked) {
+                    control.activate();
+                } else {
+                    control.deactivate();
+                }
+            }
+        </script>
+    </head>
+    <body onload="init()">
+        <h1 id="title">OpenLayers Page Position Test</h1>
+
+        <p id="shortdesc">
+            Test if borders and scroll position cause unwanted offsets on the
+            mouse positions reported by map events.
+        </p>
+        <div id="mapwrap">
+            <div id="map"></div>
+        </div>
+
+        <ul id="controlToggle">
+            <li>
+                <input type="radio" name="type" value="none" id="noneToggle"
+                       onclick="toggleControl(this);" checked="checked" />
+                <label for="noneToggle">navigate</label>
+            </li>
+            <li>
+                <input type="radio" name="type" value="draw" id="lineToggle" onclick="toggleControl(this);" />
+                <label for="lineToggle">draw line</label>
+            </li>
+        </ul>
+
+        <div id="docs">
+            <p>This map's div has a border and absolute positioning, wrapped
+                by a container which also has a border. The page is also
+                scrollable. Neither the borders nor scrolling the page should
+                result in unwanted offsets on pixel positions reported by map
+                events.</p>
+            <p>With the line drawing control active, click on the map to add a
+                point.  The point should be drawn at the exact mouse location.</p>
+            <p>With the navigation control active, shift-drag a zoom rectangle.
+                The rectangle's corner should align exactly with the mouse
+                cursor.</p>
+            <p>Scroll the page and repeat the above tests.</p>
+            <div id="scrollspace"><div>
+        </div>
+    </body>
+</html>

Modified: sandbox/ahocevar/playground/tests/manual/tiles-loading.html
===================================================================
--- sandbox/ahocevar/playground/tests/manual/tiles-loading.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/tiles-loading.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -14,6 +14,7 @@
             width: 512px;
             height: 512px;
         }
+
     </style>
 
     <script src='http://maps.google.com/maps?file=api&amp;v=2.82&amp;key=ABQIAAAAjpkAC9ePGem0lIq5XcMiuhR_wWLPFku8Ix9i2SXYRVK3e45q1BQUd_beF8dtzKET_EteAjPdGDwqpQ'></script>
@@ -22,9 +23,8 @@
         // make map available for easy debugging
         var map;
 
-        // avoid pink tiles
+        // increase reload attempts 
         OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
 
         function init(){
             var options = {

Modified: sandbox/ahocevar/playground/tests/manual/ve-opacity.html
===================================================================
--- sandbox/ahocevar/playground/tests/manual/ve-opacity.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/manual/ve-opacity.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -8,7 +8,7 @@
         }
     </style>
 
-    <script src='http://dev.virtualearth.net/mapcontrol/v3/mapcontrol.js'></script>
+    <script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>
 
     <script src="../../lib/OpenLayers.js"></script>
     <script type="text/javascript">
@@ -16,9 +16,8 @@
         // make map available for easy debugging
         var map;
 
-        // avoid pink tiles
+        // increase reload attempts 
         OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
-        OpenLayers.Util.onImageLoadErrorColor = "transparent";
 
         function init(){
             var options = {

Modified: sandbox/ahocevar/playground/tests/run-tests.html
===================================================================
--- sandbox/ahocevar/playground/tests/run-tests.html	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/run-tests.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -917,8 +917,8 @@
 			}
 		}else { // otherwise (not IE) it ought to work like this
 			for( var i in Test.AnotherWay._g_test_iframe) {
-				// Hack to prevent failure in FF3.0b1 
-                if (i == "innerWidth" || i == "innerHeight") { continue; }
+				// Hack to prevent failure in FF3.0b1 (innerWidth/innerHeight) and FF>=3.5 (sessionStorage)
+                if (i == "innerWidth" || i == "innerHeight" || i == "sessionStorage") { continue; }
                 if( typeof( Test.AnotherWay._g_test_iframe[i] )=='function' ) {
 					if( i.substring( 0, 4 )=="test" ) {
 						test_page.test_objects.push( new Test.AnotherWay._test_object_t( i ) );


Property changes on: sandbox/ahocevar/playground/tests/speed
___________________________________________________________________
Modified: svn:mergeinfo
   - 
   + /trunk/openlayers/tests/speed:7565-7622,7733-10919

Copied: sandbox/ahocevar/playground/tests/speed/wmscaps.html (from rev 10919, trunk/openlayers/tests/speed/wmscaps.html)
===================================================================
--- sandbox/ahocevar/playground/tests/speed/wmscaps.html	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/speed/wmscaps.html	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,52 @@
+<html>
+    <head>
+        <title>WMS Capabilities Speed Test</title>
+        <script src="../../lib/OpenLayers.js"></script>
+        <script src="wmscaps.js"></script>
+        <script>
+            var data;
+            var stats = [];
+
+            function parseCaps(id, done) {
+                var format = new OpenLayers.Format.WMSCapabilities();
+                data = format.read(caps);
+                done(id);
+            }
+
+            function run(func, x) {
+                document.getElementById("out").innerHTML = "running ...";
+                var starts = {};
+                var elapsed = 0;
+                completed = 0;
+                function callback(id) {
+                    elapsed += new Date() - starts[id];
+                    ++completed;
+                    if (completed === x) {
+                        report(x, elapsed);
+                    }
+                }
+                var runner;
+                for (var i=0; i<x; i++) {
+                    runner = createRunner(i, starts, func, callback);
+                    window.setTimeout(runner, 0);
+                }
+            }
+            
+            function createRunner(id, starts, func, done) {
+                return function() {
+                    starts[id] = new Date();
+                    func(id, done);
+                }
+            }
+
+            function report(x, elapsed) {
+                document.getElementById("out").innerHTML = elapsed + " ms for " + x + " runs (" + elapsed/x + " ms average)";
+            }
+
+        </script>
+    </head>
+    <body>
+        <a onclick="javascript:run(parseCaps, 5); return false" href="#">Run</a>
+        <div id="out"></div>
+    </body>
+</html>

Copied: sandbox/ahocevar/playground/tests/speed/wmscaps.js (from rev 10919, trunk/openlayers/tests/speed/wmscaps.js)
===================================================================
--- sandbox/ahocevar/playground/tests/speed/wmscaps.js	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/speed/wmscaps.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,4956 @@
+var caps = 
+'<?xml version="1.0" encoding="UTF-8"?>' +
+'<!DOCTYPE WMT_MS_Capabilities SYSTEM "http://demo.opengeo.org/geoserver/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd">' +
+'<WMT_MS_Capabilities version="1.1.1" updateSequence="145">' +
+'  <Service>' +
+'    <Name>OGC:WMS</Name>' +
+'    <Title>GeoServer Web Map Service</Title>' +
+'    <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>' +
+'    <KeywordList>' +
+'      <Keyword>WFS</Keyword>' +
+'      <Keyword>WMS</Keyword>' +
+'      <Keyword>GEOSERVER</Keyword>' +
+'    </KeywordList>' +
+'    <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms"/>' +
+'    <ContactInformation>' +
+'      <ContactPersonPrimary>' +
+'        <ContactPerson>Claudius Ptolomaeus</ContactPerson>' +
+'        <ContactOrganization>The ancient geographes INC</ContactOrganization>' +
+'      </ContactPersonPrimary>' +
+'      <ContactPosition>Chief geographer</ContactPosition>' +
+'      <ContactAddress>' +
+'        <AddressType>Work</AddressType>' +
+'        <Address/>' +
+'        <City>Alexandria</City>' +
+'        <StateOrProvince/>' +
+'        <PostCode/>' +
+'        <Country>Egypt</Country>' +
+'      </ContactAddress>' +
+'      <ContactVoiceTelephone/>' +
+'      <ContactFacsimileTelephone/>' +
+'      <ContactElectronicMailAddress>claudius.ptolomaeus at gmail.com</ContactElectronicMailAddress>' +
+'    </ContactInformation>' +
+'    <Fees>NONE</Fees>' +
+'    <AccessConstraints>NONE</AccessConstraints>' +
+'  </Service>' +
+'  <Capability>' +
+'    <Request>' +
+'      <GetCapabilities>' +
+'        <Format>application/vnd.ogc.wms_xml</Format>' +
+'        <DCPType>' +
+'          <HTTP>' +
+'            <Get>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Get>' +
+'            <Post>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Post>' +
+'          </HTTP>' +
+'        </DCPType>' +
+'      </GetCapabilities>' +
+'      <GetMap>' +
+'        <Format>image/png</Format>' +
+'        <Format>application/atom xml</Format>' +
+'        <Format>application/atom+xml</Format>' +
+'        <Format>application/openlayers</Format>' +
+'        <Format>application/pdf</Format>' +
+'        <Format>application/rss xml</Format>' +
+'        <Format>application/rss+xml</Format>' +
+'        <Format>application/vnd.google-earth.kml</Format>' +
+'        <Format>application/vnd.google-earth.kml xml</Format>' +
+'        <Format>application/vnd.google-earth.kml+xml</Format>' +
+'        <Format>application/vnd.google-earth.kmz</Format>' +
+'        <Format>application/vnd.google-earth.kmz xml</Format>' +
+'        <Format>application/vnd.google-earth.kmz+xml</Format>' +
+'        <Format>atom</Format>' +
+'        <Format>image/geotiff</Format>' +
+'        <Format>image/geotiff8</Format>' +
+'        <Format>image/gif</Format>' +
+'        <Format>image/jpeg</Format>' +
+'        <Format>image/png8</Format>' +
+'        <Format>image/svg</Format>' +
+'        <Format>image/svg xml</Format>' +
+'        <Format>image/svg+xml</Format>' +
+'        <Format>image/tiff</Format>' +
+'        <Format>image/tiff8</Format>' +
+'        <Format>kml</Format>' +
+'        <Format>kmz</Format>' +
+'        <Format>openlayers</Format>' +
+'        <Format>rss</Format>' +
+'        <DCPType>' +
+'          <HTTP>' +
+'            <Get>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Get>' +
+'          </HTTP>' +
+'        </DCPType>' +
+'      </GetMap>' +
+'      <GetFeatureInfo>' +
+'        <Format>text/plain</Format>' +
+'        <Format>text/html</Format>' +
+'        <Format>application/vnd.ogc.gml</Format>' +
+'        <DCPType>' +
+'          <HTTP>' +
+'            <Get>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Get>' +
+'            <Post>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Post>' +
+'          </HTTP>' +
+'        </DCPType>' +
+'      </GetFeatureInfo>' +
+'      <DescribeLayer>' +
+'        <Format>application/vnd.ogc.wms_xml</Format>' +
+'        <DCPType>' +
+'          <HTTP>' +
+'            <Get>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Get>' +
+'          </HTTP>' +
+'        </DCPType>' +
+'      </DescribeLayer>' +
+'      <GetLegendGraphic>' +
+'        <Format>image/png</Format>' +
+'        <Format>image/jpeg</Format>' +
+'        <Format>image/gif</Format>' +
+'        <DCPType>' +
+'          <HTTP>' +
+'            <Get>' +
+'              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>' +
+'            </Get>' +
+'          </HTTP>' +
+'        </DCPType>' +
+'      </GetLegendGraphic>' +
+'    </Request>' +
+'    <Exception>' +
+'      <Format>application/vnd.ogc.se_xml</Format>' +
+'    </Exception>' +
+'    <UserDefinedSymbolization SupportSLD="1" UserLayer="1" UserStyle="1" RemoteWFS="1"/>' +
+'    <Layer>' +
+'      <Title>GeoServer Web Map Service</Title>' +
+'      <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>' +
+'      <!--All supported EPSG projections:-->' +
+'      <SRS>EPSG:WGS84(DD)</SRS>' +
+'      <SRS>EPSG:2000</SRS>' +
+'      <SRS>EPSG:2001</SRS>' +
+'      <SRS>EPSG:2002</SRS>' +
+'      <SRS>EPSG:2003</SRS>' +
+'      <SRS>EPSG:2004</SRS>' +
+'      <SRS>EPSG:2005</SRS>' +
+'      <SRS>EPSG:2006</SRS>' +
+'      <SRS>EPSG:2007</SRS>' +
+'      <SRS>EPSG:2008</SRS>' +
+'      <SRS>EPSG:2009</SRS>' +
+'      <SRS>EPSG:2010</SRS>' +
+'      <SRS>EPSG:2011</SRS>' +
+'      <SRS>EPSG:2012</SRS>' +
+'      <SRS>EPSG:2013</SRS>' +
+'      <SRS>EPSG:2014</SRS>' +
+'      <SRS>EPSG:2015</SRS>' +
+'      <SRS>EPSG:2016</SRS>' +
+'      <SRS>EPSG:2017</SRS>' +
+'      <SRS>EPSG:2018</SRS>' +
+'      <SRS>EPSG:2019</SRS>' +
+'      <SRS>EPSG:2020</SRS>' +
+'      <SRS>EPSG:2021</SRS>' +
+'      <SRS>EPSG:2022</SRS>' +
+'      <SRS>EPSG:2023</SRS>' +
+'      <SRS>EPSG:2024</SRS>' +
+'      <SRS>EPSG:2025</SRS>' +
+'      <SRS>EPSG:2026</SRS>' +
+'      <SRS>EPSG:2027</SRS>' +
+'      <SRS>EPSG:2028</SRS>' +
+'      <SRS>EPSG:2029</SRS>' +
+'      <SRS>EPSG:2030</SRS>' +
+'      <SRS>EPSG:2031</SRS>' +
+'      <SRS>EPSG:2032</SRS>' +
+'      <SRS>EPSG:2033</SRS>' +
+'      <SRS>EPSG:2034</SRS>' +
+'      <SRS>EPSG:2035</SRS>' +
+'      <SRS>EPSG:2036</SRS>' +
+'      <SRS>EPSG:2037</SRS>' +
+'      <SRS>EPSG:2038</SRS>' +
+'      <SRS>EPSG:2039</SRS>' +
+'      <SRS>EPSG:2040</SRS>' +
+'      <SRS>EPSG:2041</SRS>' +
+'      <SRS>EPSG:2042</SRS>' +
+'      <SRS>EPSG:2043</SRS>' +
+'      <SRS>EPSG:2044</SRS>' +
+'      <SRS>EPSG:2045</SRS>' +
+'      <SRS>EPSG:2046</SRS>' +
+'      <SRS>EPSG:2047</SRS>' +
+'      <SRS>EPSG:2048</SRS>' +
+'      <SRS>EPSG:2049</SRS>' +
+'      <SRS>EPSG:2050</SRS>' +
+'      <SRS>EPSG:2051</SRS>' +
+'      <SRS>EPSG:2052</SRS>' +
+'      <SRS>EPSG:2053</SRS>' +
+'      <SRS>EPSG:2054</SRS>' +
+'      <SRS>EPSG:2055</SRS>' +
+'      <SRS>EPSG:2056</SRS>' +
+'      <SRS>EPSG:2057</SRS>' +
+'      <SRS>EPSG:2058</SRS>' +
+'      <SRS>EPSG:2059</SRS>' +
+'      <SRS>EPSG:2060</SRS>' +
+'      <SRS>EPSG:2061</SRS>' +
+'      <SRS>EPSG:2062</SRS>' +
+'      <SRS>EPSG:2063</SRS>' +
+'      <SRS>EPSG:2064</SRS>' +
+'      <SRS>EPSG:2065</SRS>' +
+'      <SRS>EPSG:2066</SRS>' +
+'      <SRS>EPSG:2067</SRS>' +
+'      <SRS>EPSG:2068</SRS>' +
+'      <SRS>EPSG:2069</SRS>' +
+'      <SRS>EPSG:2070</SRS>' +
+'      <SRS>EPSG:2071</SRS>' +
+'      <SRS>EPSG:2072</SRS>' +
+'      <SRS>EPSG:2073</SRS>' +
+'      <SRS>EPSG:2074</SRS>' +
+'      <SRS>EPSG:2075</SRS>' +
+'      <SRS>EPSG:2076</SRS>' +
+'      <SRS>EPSG:2077</SRS>' +
+'      <SRS>EPSG:2078</SRS>' +
+'      <SRS>EPSG:2079</SRS>' +
+'      <SRS>EPSG:2080</SRS>' +
+'      <SRS>EPSG:2081</SRS>' +
+'      <SRS>EPSG:2082</SRS>' +
+'      <SRS>EPSG:2083</SRS>' +
+'      <SRS>EPSG:2084</SRS>' +
+'      <SRS>EPSG:2085</SRS>' +
+'      <SRS>EPSG:2086</SRS>' +
+'      <SRS>EPSG:2087</SRS>' +
+'      <SRS>EPSG:2088</SRS>' +
+'      <SRS>EPSG:2089</SRS>' +
+'      <SRS>EPSG:2090</SRS>' +
+'      <SRS>EPSG:2091</SRS>' +
+'      <SRS>EPSG:2092</SRS>' +
+'      <SRS>EPSG:2093</SRS>' +
+'      <SRS>EPSG:2094</SRS>' +
+'      <SRS>EPSG:2095</SRS>' +
+'      <SRS>EPSG:2096</SRS>' +
+'      <SRS>EPSG:2097</SRS>' +
+'      <SRS>EPSG:2098</SRS>' +
+'      <SRS>EPSG:2099</SRS>' +
+'      <SRS>EPSG:2100</SRS>' +
+'      <SRS>EPSG:2101</SRS>' +
+'      <SRS>EPSG:2102</SRS>' +
+'      <SRS>EPSG:2103</SRS>' +
+'      <SRS>EPSG:2104</SRS>' +
+'      <SRS>EPSG:2105</SRS>' +
+'      <SRS>EPSG:2106</SRS>' +
+'      <SRS>EPSG:2107</SRS>' +
+'      <SRS>EPSG:2108</SRS>' +
+'      <SRS>EPSG:2109</SRS>' +
+'      <SRS>EPSG:2110</SRS>' +
+'      <SRS>EPSG:2111</SRS>' +
+'      <SRS>EPSG:2112</SRS>' +
+'      <SRS>EPSG:2113</SRS>' +
+'      <SRS>EPSG:2114</SRS>' +
+'      <SRS>EPSG:2115</SRS>' +
+'      <SRS>EPSG:2116</SRS>' +
+'      <SRS>EPSG:2117</SRS>' +
+'      <SRS>EPSG:2118</SRS>' +
+'      <SRS>EPSG:2119</SRS>' +
+'      <SRS>EPSG:2120</SRS>' +
+'      <SRS>EPSG:2121</SRS>' +
+'      <SRS>EPSG:2122</SRS>' +
+'      <SRS>EPSG:2123</SRS>' +
+'      <SRS>EPSG:2124</SRS>' +
+'      <SRS>EPSG:2125</SRS>' +
+'      <SRS>EPSG:2126</SRS>' +
+'      <SRS>EPSG:2127</SRS>' +
+'      <SRS>EPSG:2128</SRS>' +
+'      <SRS>EPSG:2129</SRS>' +
+'      <SRS>EPSG:2130</SRS>' +
+'      <SRS>EPSG:2131</SRS>' +
+'      <SRS>EPSG:2132</SRS>' +
+'      <SRS>EPSG:2133</SRS>' +
+'      <SRS>EPSG:2134</SRS>' +
+'      <SRS>EPSG:2135</SRS>' +
+'      <SRS>EPSG:2136</SRS>' +
+'      <SRS>EPSG:2137</SRS>' +
+'      <SRS>EPSG:2138</SRS>' +
+'      <SRS>EPSG:2139</SRS>' +
+'      <SRS>EPSG:2140</SRS>' +
+'      <SRS>EPSG:2141</SRS>' +
+'      <SRS>EPSG:2142</SRS>' +
+'      <SRS>EPSG:2143</SRS>' +
+'      <SRS>EPSG:2144</SRS>' +
+'      <SRS>EPSG:2145</SRS>' +
+'      <SRS>EPSG:2146</SRS>' +
+'      <SRS>EPSG:2147</SRS>' +
+'      <SRS>EPSG:2148</SRS>' +
+'      <SRS>EPSG:2149</SRS>' +
+'      <SRS>EPSG:2150</SRS>' +
+'      <SRS>EPSG:2151</SRS>' +
+'      <SRS>EPSG:2152</SRS>' +
+'      <SRS>EPSG:2153</SRS>' +
+'      <SRS>EPSG:2154</SRS>' +
+'      <SRS>EPSG:2155</SRS>' +
+'      <SRS>EPSG:2156</SRS>' +
+'      <SRS>EPSG:2157</SRS>' +
+'      <SRS>EPSG:2158</SRS>' +
+'      <SRS>EPSG:2159</SRS>' +
+'      <SRS>EPSG:2160</SRS>' +
+'      <SRS>EPSG:2161</SRS>' +
+'      <SRS>EPSG:2162</SRS>' +
+'      <SRS>EPSG:2163</SRS>' +
+'      <SRS>EPSG:2164</SRS>' +
+'      <SRS>EPSG:2165</SRS>' +
+'      <SRS>EPSG:2166</SRS>' +
+'      <SRS>EPSG:2167</SRS>' +
+'      <SRS>EPSG:2168</SRS>' +
+'      <SRS>EPSG:2169</SRS>' +
+'      <SRS>EPSG:2170</SRS>' +
+'      <SRS>EPSG:2171</SRS>' +
+'      <SRS>EPSG:2172</SRS>' +
+'      <SRS>EPSG:2173</SRS>' +
+'      <SRS>EPSG:2174</SRS>' +
+'      <SRS>EPSG:2175</SRS>' +
+'      <SRS>EPSG:2176</SRS>' +
+'      <SRS>EPSG:2177</SRS>' +
+'      <SRS>EPSG:2178</SRS>' +
+'      <SRS>EPSG:2179</SRS>' +
+'      <SRS>EPSG:2180</SRS>' +
+'      <SRS>EPSG:2188</SRS>' +
+'      <SRS>EPSG:2189</SRS>' +
+'      <SRS>EPSG:2190</SRS>' +
+'      <SRS>EPSG:2191</SRS>' +
+'      <SRS>EPSG:2192</SRS>' +
+'      <SRS>EPSG:2193</SRS>' +
+'      <SRS>EPSG:2194</SRS>' +
+'      <SRS>EPSG:2195</SRS>' +
+'      <SRS>EPSG:2196</SRS>' +
+'      <SRS>EPSG:2197</SRS>' +
+'      <SRS>EPSG:2198</SRS>' +
+'      <SRS>EPSG:2199</SRS>' +
+'      <SRS>EPSG:2200</SRS>' +
+'      <SRS>EPSG:2201</SRS>' +
+'      <SRS>EPSG:2202</SRS>' +
+'      <SRS>EPSG:2203</SRS>' +
+'      <SRS>EPSG:2204</SRS>' +
+'      <SRS>EPSG:2205</SRS>' +
+'      <SRS>EPSG:2206</SRS>' +
+'      <SRS>EPSG:2207</SRS>' +
+'      <SRS>EPSG:2208</SRS>' +
+'      <SRS>EPSG:2209</SRS>' +
+'      <SRS>EPSG:2210</SRS>' +
+'      <SRS>EPSG:2211</SRS>' +
+'      <SRS>EPSG:2212</SRS>' +
+'      <SRS>EPSG:2213</SRS>' +
+'      <SRS>EPSG:2214</SRS>' +
+'      <SRS>EPSG:2215</SRS>' +
+'      <SRS>EPSG:2216</SRS>' +
+'      <SRS>EPSG:2217</SRS>' +
+'      <SRS>EPSG:2218</SRS>' +
+'      <SRS>EPSG:2219</SRS>' +
+'      <SRS>EPSG:2220</SRS>' +
+'      <SRS>EPSG:2221</SRS>' +
+'      <SRS>EPSG:2222</SRS>' +
+'      <SRS>EPSG:2223</SRS>' +
+'      <SRS>EPSG:2224</SRS>' +
+'      <SRS>EPSG:2225</SRS>' +
+'      <SRS>EPSG:2226</SRS>' +
+'      <SRS>EPSG:2227</SRS>' +
+'      <SRS>EPSG:2228</SRS>' +
+'      <SRS>EPSG:2229</SRS>' +
+'      <SRS>EPSG:2230</SRS>' +
+'      <SRS>EPSG:2231</SRS>' +
+'      <SRS>EPSG:2232</SRS>' +
+'      <SRS>EPSG:2233</SRS>' +
+'      <SRS>EPSG:2234</SRS>' +
+'      <SRS>EPSG:2235</SRS>' +
+'      <SRS>EPSG:2236</SRS>' +
+'      <SRS>EPSG:2237</SRS>' +
+'      <SRS>EPSG:2238</SRS>' +
+'      <SRS>EPSG:2239</SRS>' +
+'      <SRS>EPSG:2240</SRS>' +
+'      <SRS>EPSG:2241</SRS>' +
+'      <SRS>EPSG:2242</SRS>' +
+'      <SRS>EPSG:2243</SRS>' +
+'      <SRS>EPSG:2244</SRS>' +
+'      <SRS>EPSG:2245</SRS>' +
+'      <SRS>EPSG:2246</SRS>' +
+'      <SRS>EPSG:2247</SRS>' +
+'      <SRS>EPSG:2248</SRS>' +
+'      <SRS>EPSG:2249</SRS>' +
+'      <SRS>EPSG:2250</SRS>' +
+'      <SRS>EPSG:2251</SRS>' +
+'      <SRS>EPSG:2252</SRS>' +
+'      <SRS>EPSG:2253</SRS>' +
+'      <SRS>EPSG:2254</SRS>' +
+'      <SRS>EPSG:2255</SRS>' +
+'      <SRS>EPSG:2256</SRS>' +
+'      <SRS>EPSG:2257</SRS>' +
+'      <SRS>EPSG:2258</SRS>' +
+'      <SRS>EPSG:2259</SRS>' +
+'      <SRS>EPSG:2260</SRS>' +
+'      <SRS>EPSG:2261</SRS>' +
+'      <SRS>EPSG:2262</SRS>' +
+'      <SRS>EPSG:2263</SRS>' +
+'      <SRS>EPSG:2264</SRS>' +
+'      <SRS>EPSG:2265</SRS>' +
+'      <SRS>EPSG:2266</SRS>' +
+'      <SRS>EPSG:2267</SRS>' +
+'      <SRS>EPSG:2268</SRS>' +
+'      <SRS>EPSG:2269</SRS>' +
+'      <SRS>EPSG:2270</SRS>' +
+'      <SRS>EPSG:2271</SRS>' +
+'      <SRS>EPSG:2272</SRS>' +
+'      <SRS>EPSG:2273</SRS>' +
+'      <SRS>EPSG:2274</SRS>' +
+'      <SRS>EPSG:2275</SRS>' +
+'      <SRS>EPSG:2276</SRS>' +
+'      <SRS>EPSG:2277</SRS>' +
+'      <SRS>EPSG:2278</SRS>' +
+'      <SRS>EPSG:2279</SRS>' +
+'      <SRS>EPSG:2280</SRS>' +
+'      <SRS>EPSG:2281</SRS>' +
+'      <SRS>EPSG:2282</SRS>' +
+'      <SRS>EPSG:2283</SRS>' +
+'      <SRS>EPSG:2284</SRS>' +
+'      <SRS>EPSG:2285</SRS>' +
+'      <SRS>EPSG:2286</SRS>' +
+'      <SRS>EPSG:2287</SRS>' +
+'      <SRS>EPSG:2288</SRS>' +
+'      <SRS>EPSG:2289</SRS>' +
+'      <SRS>EPSG:2290</SRS>' +
+'      <SRS>EPSG:2291</SRS>' +
+'      <SRS>EPSG:2292</SRS>' +
+'      <SRS>EPSG:2294</SRS>' +
+'      <SRS>EPSG:2295</SRS>' +
+'      <SRS>EPSG:2296</SRS>' +
+'      <SRS>EPSG:2297</SRS>' +
+'      <SRS>EPSG:2298</SRS>' +
+'      <SRS>EPSG:2299</SRS>' +
+'      <SRS>EPSG:2300</SRS>' +
+'      <SRS>EPSG:2301</SRS>' +
+'      <SRS>EPSG:2302</SRS>' +
+'      <SRS>EPSG:2303</SRS>' +
+'      <SRS>EPSG:2304</SRS>' +
+'      <SRS>EPSG:2305</SRS>' +
+'      <SRS>EPSG:2306</SRS>' +
+'      <SRS>EPSG:2307</SRS>' +
+'      <SRS>EPSG:2308</SRS>' +
+'      <SRS>EPSG:2309</SRS>' +
+'      <SRS>EPSG:2310</SRS>' +
+'      <SRS>EPSG:2311</SRS>' +
+'      <SRS>EPSG:2312</SRS>' +
+'      <SRS>EPSG:2313</SRS>' +
+'      <SRS>EPSG:2314</SRS>' +
+'      <SRS>EPSG:2315</SRS>' +
+'      <SRS>EPSG:2316</SRS>' +
+'      <SRS>EPSG:2317</SRS>' +
+'      <SRS>EPSG:2318</SRS>' +
+'      <SRS>EPSG:2319</SRS>' +
+'      <SRS>EPSG:2320</SRS>' +
+'      <SRS>EPSG:2321</SRS>' +
+'      <SRS>EPSG:2322</SRS>' +
+'      <SRS>EPSG:2323</SRS>' +
+'      <SRS>EPSG:2324</SRS>' +
+'      <SRS>EPSG:2325</SRS>' +
+'      <SRS>EPSG:2326</SRS>' +
+'      <SRS>EPSG:2327</SRS>' +
+'      <SRS>EPSG:2328</SRS>' +
+'      <SRS>EPSG:2329</SRS>' +
+'      <SRS>EPSG:2330</SRS>' +
+'      <SRS>EPSG:2331</SRS>' +
+'      <SRS>EPSG:2332</SRS>' +
+'      <SRS>EPSG:2333</SRS>' +
+'      <SRS>EPSG:2334</SRS>' +
+'      <SRS>EPSG:2335</SRS>' +
+'      <SRS>EPSG:2336</SRS>' +
+'      <SRS>EPSG:2337</SRS>' +
+'      <SRS>EPSG:2338</SRS>' +
+'      <SRS>EPSG:2339</SRS>' +
+'      <SRS>EPSG:2340</SRS>' +
+'      <SRS>EPSG:2341</SRS>' +
+'      <SRS>EPSG:2342</SRS>' +
+'      <SRS>EPSG:2343</SRS>' +
+'      <SRS>EPSG:2344</SRS>' +
+'      <SRS>EPSG:2345</SRS>' +
+'      <SRS>EPSG:2346</SRS>' +
+'      <SRS>EPSG:2347</SRS>' +
+'      <SRS>EPSG:2348</SRS>' +
+'      <SRS>EPSG:2349</SRS>' +
+'      <SRS>EPSG:2350</SRS>' +
+'      <SRS>EPSG:2351</SRS>' +
+'      <SRS>EPSG:2352</SRS>' +
+'      <SRS>EPSG:2353</SRS>' +
+'      <SRS>EPSG:2354</SRS>' +
+'      <SRS>EPSG:2355</SRS>' +
+'      <SRS>EPSG:2356</SRS>' +
+'      <SRS>EPSG:2357</SRS>' +
+'      <SRS>EPSG:2358</SRS>' +
+'      <SRS>EPSG:2359</SRS>' +
+'      <SRS>EPSG:2360</SRS>' +
+'      <SRS>EPSG:2361</SRS>' +
+'      <SRS>EPSG:2362</SRS>' +
+'      <SRS>EPSG:2363</SRS>' +
+'      <SRS>EPSG:2364</SRS>' +
+'      <SRS>EPSG:2365</SRS>' +
+'      <SRS>EPSG:2366</SRS>' +
+'      <SRS>EPSG:2367</SRS>' +
+'      <SRS>EPSG:2368</SRS>' +
+'      <SRS>EPSG:2369</SRS>' +
+'      <SRS>EPSG:2370</SRS>' +
+'      <SRS>EPSG:2371</SRS>' +
+'      <SRS>EPSG:2372</SRS>' +
+'      <SRS>EPSG:2373</SRS>' +
+'      <SRS>EPSG:2374</SRS>' +
+'      <SRS>EPSG:2375</SRS>' +
+'      <SRS>EPSG:2376</SRS>' +
+'      <SRS>EPSG:2377</SRS>' +
+'      <SRS>EPSG:2378</SRS>' +
+'      <SRS>EPSG:2379</SRS>' +
+'      <SRS>EPSG:2380</SRS>' +
+'      <SRS>EPSG:2381</SRS>' +
+'      <SRS>EPSG:2382</SRS>' +
+'      <SRS>EPSG:2383</SRS>' +
+'      <SRS>EPSG:2384</SRS>' +
+'      <SRS>EPSG:2385</SRS>' +
+'      <SRS>EPSG:2386</SRS>' +
+'      <SRS>EPSG:2387</SRS>' +
+'      <SRS>EPSG:2388</SRS>' +
+'      <SRS>EPSG:2389</SRS>' +
+'      <SRS>EPSG:2390</SRS>' +
+'      <SRS>EPSG:2391</SRS>' +
+'      <SRS>EPSG:2392</SRS>' +
+'      <SRS>EPSG:2393</SRS>' +
+'      <SRS>EPSG:2394</SRS>' +
+'      <SRS>EPSG:2395</SRS>' +
+'      <SRS>EPSG:2396</SRS>' +
+'      <SRS>EPSG:2397</SRS>' +
+'      <SRS>EPSG:2398</SRS>' +
+'      <SRS>EPSG:2399</SRS>' +
+'      <SRS>EPSG:2400</SRS>' +
+'      <SRS>EPSG:2401</SRS>' +
+'      <SRS>EPSG:2402</SRS>' +
+'      <SRS>EPSG:2403</SRS>' +
+'      <SRS>EPSG:2404</SRS>' +
+'      <SRS>EPSG:2405</SRS>' +
+'      <SRS>EPSG:2406</SRS>' +
+'      <SRS>EPSG:2407</SRS>' +
+'      <SRS>EPSG:2408</SRS>' +
+'      <SRS>EPSG:2409</SRS>' +
+'      <SRS>EPSG:2410</SRS>' +
+'      <SRS>EPSG:2411</SRS>' +
+'      <SRS>EPSG:2412</SRS>' +
+'      <SRS>EPSG:2413</SRS>' +
+'      <SRS>EPSG:2414</SRS>' +
+'      <SRS>EPSG:2415</SRS>' +
+'      <SRS>EPSG:2416</SRS>' +
+'      <SRS>EPSG:2417</SRS>' +
+'      <SRS>EPSG:2418</SRS>' +
+'      <SRS>EPSG:2419</SRS>' +
+'      <SRS>EPSG:2420</SRS>' +
+'      <SRS>EPSG:2421</SRS>' +
+'      <SRS>EPSG:2422</SRS>' +
+'      <SRS>EPSG:2423</SRS>' +
+'      <SRS>EPSG:2424</SRS>' +
+'      <SRS>EPSG:2425</SRS>' +
+'      <SRS>EPSG:2426</SRS>' +
+'      <SRS>EPSG:2427</SRS>' +
+'      <SRS>EPSG:2428</SRS>' +
+'      <SRS>EPSG:2429</SRS>' +
+'      <SRS>EPSG:2430</SRS>' +
+'      <SRS>EPSG:2431</SRS>' +
+'      <SRS>EPSG:2432</SRS>' +
+'      <SRS>EPSG:2433</SRS>' +
+'      <SRS>EPSG:2434</SRS>' +
+'      <SRS>EPSG:2435</SRS>' +
+'      <SRS>EPSG:2436</SRS>' +
+'      <SRS>EPSG:2437</SRS>' +
+'      <SRS>EPSG:2438</SRS>' +
+'      <SRS>EPSG:2439</SRS>' +
+'      <SRS>EPSG:2440</SRS>' +
+'      <SRS>EPSG:2441</SRS>' +
+'      <SRS>EPSG:2442</SRS>' +
+'      <SRS>EPSG:2443</SRS>' +
+'      <SRS>EPSG:2444</SRS>' +
+'      <SRS>EPSG:2445</SRS>' +
+'      <SRS>EPSG:2446</SRS>' +
+'      <SRS>EPSG:2447</SRS>' +
+'      <SRS>EPSG:2448</SRS>' +
+'      <SRS>EPSG:2449</SRS>' +
+'      <SRS>EPSG:2450</SRS>' +
+'      <SRS>EPSG:2451</SRS>' +
+'      <SRS>EPSG:2452</SRS>' +
+'      <SRS>EPSG:2453</SRS>' +
+'      <SRS>EPSG:2454</SRS>' +
+'      <SRS>EPSG:2455</SRS>' +
+'      <SRS>EPSG:2456</SRS>' +
+'      <SRS>EPSG:2457</SRS>' +
+'      <SRS>EPSG:2458</SRS>' +
+'      <SRS>EPSG:2459</SRS>' +
+'      <SRS>EPSG:2460</SRS>' +
+'      <SRS>EPSG:2461</SRS>' +
+'      <SRS>EPSG:2462</SRS>' +
+'      <SRS>EPSG:2463</SRS>' +
+'      <SRS>EPSG:2464</SRS>' +
+'      <SRS>EPSG:2465</SRS>' +
+'      <SRS>EPSG:2466</SRS>' +
+'      <SRS>EPSG:2467</SRS>' +
+'      <SRS>EPSG:2468</SRS>' +
+'      <SRS>EPSG:2469</SRS>' +
+'      <SRS>EPSG:2470</SRS>' +
+'      <SRS>EPSG:2471</SRS>' +
+'      <SRS>EPSG:2472</SRS>' +
+'      <SRS>EPSG:2473</SRS>' +
+'      <SRS>EPSG:2474</SRS>' +
+'      <SRS>EPSG:2475</SRS>' +
+'      <SRS>EPSG:2476</SRS>' +
+'      <SRS>EPSG:2477</SRS>' +
+'      <SRS>EPSG:2478</SRS>' +
+'      <SRS>EPSG:2479</SRS>' +
+'      <SRS>EPSG:2480</SRS>' +
+'      <SRS>EPSG:2481</SRS>' +
+'      <SRS>EPSG:2482</SRS>' +
+'      <SRS>EPSG:2483</SRS>' +
+'      <SRS>EPSG:2484</SRS>' +
+'      <SRS>EPSG:2485</SRS>' +
+'      <SRS>EPSG:2486</SRS>' +
+'      <SRS>EPSG:2487</SRS>' +
+'      <SRS>EPSG:2488</SRS>' +
+'      <SRS>EPSG:2489</SRS>' +
+'      <SRS>EPSG:2490</SRS>' +
+'      <SRS>EPSG:2491</SRS>' +
+'      <SRS>EPSG:2492</SRS>' +
+'      <SRS>EPSG:2493</SRS>' +
+'      <SRS>EPSG:2494</SRS>' +
+'      <SRS>EPSG:2495</SRS>' +
+'      <SRS>EPSG:2496</SRS>' +
+'      <SRS>EPSG:2497</SRS>' +
+'      <SRS>EPSG:2498</SRS>' +
+'      <SRS>EPSG:2499</SRS>' +
+'      <SRS>EPSG:2500</SRS>' +
+'      <SRS>EPSG:2501</SRS>' +
+'      <SRS>EPSG:2502</SRS>' +
+'      <SRS>EPSG:2503</SRS>' +
+'      <SRS>EPSG:2504</SRS>' +
+'      <SRS>EPSG:2505</SRS>' +
+'      <SRS>EPSG:2506</SRS>' +
+'      <SRS>EPSG:2507</SRS>' +
+'      <SRS>EPSG:2508</SRS>' +
+'      <SRS>EPSG:2509</SRS>' +
+'      <SRS>EPSG:2510</SRS>' +
+'      <SRS>EPSG:2511</SRS>' +
+'      <SRS>EPSG:2512</SRS>' +
+'      <SRS>EPSG:2513</SRS>' +
+'      <SRS>EPSG:2514</SRS>' +
+'      <SRS>EPSG:2515</SRS>' +
+'      <SRS>EPSG:2516</SRS>' +
+'      <SRS>EPSG:2517</SRS>' +
+'      <SRS>EPSG:2518</SRS>' +
+'      <SRS>EPSG:2519</SRS>' +
+'      <SRS>EPSG:2520</SRS>' +
+'      <SRS>EPSG:2521</SRS>' +
+'      <SRS>EPSG:2522</SRS>' +
+'      <SRS>EPSG:2523</SRS>' +
+'      <SRS>EPSG:2524</SRS>' +
+'      <SRS>EPSG:2525</SRS>' +
+'      <SRS>EPSG:2526</SRS>' +
+'      <SRS>EPSG:2527</SRS>' +
+'      <SRS>EPSG:2528</SRS>' +
+'      <SRS>EPSG:2529</SRS>' +
+'      <SRS>EPSG:2530</SRS>' +
+'      <SRS>EPSG:2531</SRS>' +
+'      <SRS>EPSG:2532</SRS>' +
+'      <SRS>EPSG:2533</SRS>' +
+'      <SRS>EPSG:2534</SRS>' +
+'      <SRS>EPSG:2535</SRS>' +
+'      <SRS>EPSG:2536</SRS>' +
+'      <SRS>EPSG:2537</SRS>' +
+'      <SRS>EPSG:2538</SRS>' +
+'      <SRS>EPSG:2539</SRS>' +
+'      <SRS>EPSG:2540</SRS>' +
+'      <SRS>EPSG:2541</SRS>' +
+'      <SRS>EPSG:2542</SRS>' +
+'      <SRS>EPSG:2543</SRS>' +
+'      <SRS>EPSG:2544</SRS>' +
+'      <SRS>EPSG:2545</SRS>' +
+'      <SRS>EPSG:2546</SRS>' +
+'      <SRS>EPSG:2547</SRS>' +
+'      <SRS>EPSG:2548</SRS>' +
+'      <SRS>EPSG:2549</SRS>' +
+'      <SRS>EPSG:2550</SRS>' +
+'      <SRS>EPSG:2551</SRS>' +
+'      <SRS>EPSG:2552</SRS>' +
+'      <SRS>EPSG:2553</SRS>' +
+'      <SRS>EPSG:2554</SRS>' +
+'      <SRS>EPSG:2555</SRS>' +
+'      <SRS>EPSG:2556</SRS>' +
+'      <SRS>EPSG:2557</SRS>' +
+'      <SRS>EPSG:2558</SRS>' +
+'      <SRS>EPSG:2559</SRS>' +
+'      <SRS>EPSG:2560</SRS>' +
+'      <SRS>EPSG:2561</SRS>' +
+'      <SRS>EPSG:2562</SRS>' +
+'      <SRS>EPSG:2563</SRS>' +
+'      <SRS>EPSG:2564</SRS>' +
+'      <SRS>EPSG:2565</SRS>' +
+'      <SRS>EPSG:2566</SRS>' +
+'      <SRS>EPSG:2567</SRS>' +
+'      <SRS>EPSG:2568</SRS>' +
+'      <SRS>EPSG:2569</SRS>' +
+'      <SRS>EPSG:2570</SRS>' +
+'      <SRS>EPSG:2571</SRS>' +
+'      <SRS>EPSG:2572</SRS>' +
+'      <SRS>EPSG:2573</SRS>' +
+'      <SRS>EPSG:2574</SRS>' +
+'      <SRS>EPSG:2575</SRS>' +
+'      <SRS>EPSG:2576</SRS>' +
+'      <SRS>EPSG:2577</SRS>' +
+'      <SRS>EPSG:2578</SRS>' +
+'      <SRS>EPSG:2579</SRS>' +
+'      <SRS>EPSG:2580</SRS>' +
+'      <SRS>EPSG:2581</SRS>' +
+'      <SRS>EPSG:2582</SRS>' +
+'      <SRS>EPSG:2583</SRS>' +
+'      <SRS>EPSG:2584</SRS>' +
+'      <SRS>EPSG:2585</SRS>' +
+'      <SRS>EPSG:2586</SRS>' +
+'      <SRS>EPSG:2587</SRS>' +
+'      <SRS>EPSG:2588</SRS>' +
+'      <SRS>EPSG:2589</SRS>' +
+'      <SRS>EPSG:2590</SRS>' +
+'      <SRS>EPSG:2591</SRS>' +
+'      <SRS>EPSG:2592</SRS>' +
+'      <SRS>EPSG:2593</SRS>' +
+'      <SRS>EPSG:2594</SRS>' +
+'      <SRS>EPSG:2595</SRS>' +
+'      <SRS>EPSG:2596</SRS>' +
+'      <SRS>EPSG:2597</SRS>' +
+'      <SRS>EPSG:2598</SRS>' +
+'      <SRS>EPSG:2599</SRS>' +
+'      <SRS>EPSG:2600</SRS>' +
+'      <SRS>EPSG:2601</SRS>' +
+'      <SRS>EPSG:2602</SRS>' +
+'      <SRS>EPSG:2603</SRS>' +
+'      <SRS>EPSG:2604</SRS>' +
+'      <SRS>EPSG:2605</SRS>' +
+'      <SRS>EPSG:2606</SRS>' +
+'      <SRS>EPSG:2607</SRS>' +
+'      <SRS>EPSG:2608</SRS>' +
+'      <SRS>EPSG:2609</SRS>' +
+'      <SRS>EPSG:2610</SRS>' +
+'      <SRS>EPSG:2611</SRS>' +
+'      <SRS>EPSG:2612</SRS>' +
+'      <SRS>EPSG:2613</SRS>' +
+'      <SRS>EPSG:2614</SRS>' +
+'      <SRS>EPSG:2615</SRS>' +
+'      <SRS>EPSG:2616</SRS>' +
+'      <SRS>EPSG:2617</SRS>' +
+'      <SRS>EPSG:2618</SRS>' +
+'      <SRS>EPSG:2619</SRS>' +
+'      <SRS>EPSG:2620</SRS>' +
+'      <SRS>EPSG:2621</SRS>' +
+'      <SRS>EPSG:2622</SRS>' +
+'      <SRS>EPSG:2623</SRS>' +
+'      <SRS>EPSG:2624</SRS>' +
+'      <SRS>EPSG:2625</SRS>' +
+'      <SRS>EPSG:2626</SRS>' +
+'      <SRS>EPSG:2627</SRS>' +
+'      <SRS>EPSG:2628</SRS>' +
+'      <SRS>EPSG:2629</SRS>' +
+'      <SRS>EPSG:2630</SRS>' +
+'      <SRS>EPSG:2631</SRS>' +
+'      <SRS>EPSG:2632</SRS>' +
+'      <SRS>EPSG:2633</SRS>' +
+'      <SRS>EPSG:2634</SRS>' +
+'      <SRS>EPSG:2635</SRS>' +
+'      <SRS>EPSG:2636</SRS>' +
+'      <SRS>EPSG:2637</SRS>' +
+'      <SRS>EPSG:2638</SRS>' +
+'      <SRS>EPSG:2639</SRS>' +
+'      <SRS>EPSG:2640</SRS>' +
+'      <SRS>EPSG:2641</SRS>' +
+'      <SRS>EPSG:2642</SRS>' +
+'      <SRS>EPSG:2643</SRS>' +
+'      <SRS>EPSG:2644</SRS>' +
+'      <SRS>EPSG:2645</SRS>' +
+'      <SRS>EPSG:2646</SRS>' +
+'      <SRS>EPSG:2647</SRS>' +
+'      <SRS>EPSG:2648</SRS>' +
+'      <SRS>EPSG:2649</SRS>' +
+'      <SRS>EPSG:2650</SRS>' +
+'      <SRS>EPSG:2651</SRS>' +
+'      <SRS>EPSG:2652</SRS>' +
+'      <SRS>EPSG:2653</SRS>' +
+'      <SRS>EPSG:2654</SRS>' +
+'      <SRS>EPSG:2655</SRS>' +
+'      <SRS>EPSG:2656</SRS>' +
+'      <SRS>EPSG:2657</SRS>' +
+'      <SRS>EPSG:2658</SRS>' +
+'      <SRS>EPSG:2659</SRS>' +
+'      <SRS>EPSG:2660</SRS>' +
+'      <SRS>EPSG:2661</SRS>' +
+'      <SRS>EPSG:2662</SRS>' +
+'      <SRS>EPSG:2663</SRS>' +
+'      <SRS>EPSG:2664</SRS>' +
+'      <SRS>EPSG:2665</SRS>' +
+'      <SRS>EPSG:2666</SRS>' +
+'      <SRS>EPSG:2667</SRS>' +
+'      <SRS>EPSG:2668</SRS>' +
+'      <SRS>EPSG:2669</SRS>' +
+'      <SRS>EPSG:2670</SRS>' +
+'      <SRS>EPSG:2671</SRS>' +
+'      <SRS>EPSG:2672</SRS>' +
+'      <SRS>EPSG:2673</SRS>' +
+'      <SRS>EPSG:2674</SRS>' +
+'      <SRS>EPSG:2675</SRS>' +
+'      <SRS>EPSG:2676</SRS>' +
+'      <SRS>EPSG:2677</SRS>' +
+'      <SRS>EPSG:2678</SRS>' +
+'      <SRS>EPSG:2679</SRS>' +
+'      <SRS>EPSG:2680</SRS>' +
+'      <SRS>EPSG:2681</SRS>' +
+'      <SRS>EPSG:2682</SRS>' +
+'      <SRS>EPSG:2683</SRS>' +
+'      <SRS>EPSG:2684</SRS>' +
+'      <SRS>EPSG:2685</SRS>' +
+'      <SRS>EPSG:2686</SRS>' +
+'      <SRS>EPSG:2687</SRS>' +
+'      <SRS>EPSG:2688</SRS>' +
+'      <SRS>EPSG:2689</SRS>' +
+'      <SRS>EPSG:2690</SRS>' +
+'      <SRS>EPSG:2691</SRS>' +
+'      <SRS>EPSG:2692</SRS>' +
+'      <SRS>EPSG:2693</SRS>' +
+'      <SRS>EPSG:2694</SRS>' +
+'      <SRS>EPSG:2695</SRS>' +
+'      <SRS>EPSG:2696</SRS>' +
+'      <SRS>EPSG:2697</SRS>' +
+'      <SRS>EPSG:2698</SRS>' +
+'      <SRS>EPSG:2699</SRS>' +
+'      <SRS>EPSG:2700</SRS>' +
+'      <SRS>EPSG:2701</SRS>' +
+'      <SRS>EPSG:2702</SRS>' +
+'      <SRS>EPSG:2703</SRS>' +
+'      <SRS>EPSG:2704</SRS>' +
+'      <SRS>EPSG:2705</SRS>' +
+'      <SRS>EPSG:2706</SRS>' +
+'      <SRS>EPSG:2707</SRS>' +
+'      <SRS>EPSG:2708</SRS>' +
+'      <SRS>EPSG:2709</SRS>' +
+'      <SRS>EPSG:2710</SRS>' +
+'      <SRS>EPSG:2711</SRS>' +
+'      <SRS>EPSG:2712</SRS>' +
+'      <SRS>EPSG:2713</SRS>' +
+'      <SRS>EPSG:2714</SRS>' +
+'      <SRS>EPSG:2715</SRS>' +
+'      <SRS>EPSG:2716</SRS>' +
+'      <SRS>EPSG:2717</SRS>' +
+'      <SRS>EPSG:2718</SRS>' +
+'      <SRS>EPSG:2719</SRS>' +
+'      <SRS>EPSG:2720</SRS>' +
+'      <SRS>EPSG:2721</SRS>' +
+'      <SRS>EPSG:2722</SRS>' +
+'      <SRS>EPSG:2723</SRS>' +
+'      <SRS>EPSG:2724</SRS>' +
+'      <SRS>EPSG:2725</SRS>' +
+'      <SRS>EPSG:2726</SRS>' +
+'      <SRS>EPSG:2727</SRS>' +
+'      <SRS>EPSG:2728</SRS>' +
+'      <SRS>EPSG:2729</SRS>' +
+'      <SRS>EPSG:2730</SRS>' +
+'      <SRS>EPSG:2731</SRS>' +
+'      <SRS>EPSG:2732</SRS>' +
+'      <SRS>EPSG:2733</SRS>' +
+'      <SRS>EPSG:2734</SRS>' +
+'      <SRS>EPSG:2735</SRS>' +
+'      <SRS>EPSG:2736</SRS>' +
+'      <SRS>EPSG:2737</SRS>' +
+'      <SRS>EPSG:2738</SRS>' +
+'      <SRS>EPSG:2739</SRS>' +
+'      <SRS>EPSG:2740</SRS>' +
+'      <SRS>EPSG:2741</SRS>' +
+'      <SRS>EPSG:2742</SRS>' +
+'      <SRS>EPSG:2743</SRS>' +
+'      <SRS>EPSG:2744</SRS>' +
+'      <SRS>EPSG:2745</SRS>' +
+'      <SRS>EPSG:2746</SRS>' +
+'      <SRS>EPSG:2747</SRS>' +
+'      <SRS>EPSG:2748</SRS>' +
+'      <SRS>EPSG:2749</SRS>' +
+'      <SRS>EPSG:2750</SRS>' +
+'      <SRS>EPSG:2751</SRS>' +
+'      <SRS>EPSG:2752</SRS>' +
+'      <SRS>EPSG:2753</SRS>' +
+'      <SRS>EPSG:2754</SRS>' +
+'      <SRS>EPSG:2755</SRS>' +
+'      <SRS>EPSG:2756</SRS>' +
+'      <SRS>EPSG:2757</SRS>' +
+'      <SRS>EPSG:2758</SRS>' +
+'      <SRS>EPSG:2759</SRS>' +
+'      <SRS>EPSG:2760</SRS>' +
+'      <SRS>EPSG:2761</SRS>' +
+'      <SRS>EPSG:2762</SRS>' +
+'      <SRS>EPSG:2763</SRS>' +
+'      <SRS>EPSG:2764</SRS>' +
+'      <SRS>EPSG:2765</SRS>' +
+'      <SRS>EPSG:2766</SRS>' +
+'      <SRS>EPSG:2767</SRS>' +
+'      <SRS>EPSG:2768</SRS>' +
+'      <SRS>EPSG:2769</SRS>' +
+'      <SRS>EPSG:2770</SRS>' +
+'      <SRS>EPSG:2771</SRS>' +
+'      <SRS>EPSG:2772</SRS>' +
+'      <SRS>EPSG:2773</SRS>' +
+'      <SRS>EPSG:2774</SRS>' +
+'      <SRS>EPSG:2775</SRS>' +
+'      <SRS>EPSG:2776</SRS>' +
+'      <SRS>EPSG:2777</SRS>' +
+'      <SRS>EPSG:2778</SRS>' +
+'      <SRS>EPSG:2779</SRS>' +
+'      <SRS>EPSG:2780</SRS>' +
+'      <SRS>EPSG:2781</SRS>' +
+'      <SRS>EPSG:2782</SRS>' +
+'      <SRS>EPSG:2783</SRS>' +
+'      <SRS>EPSG:2784</SRS>' +
+'      <SRS>EPSG:2785</SRS>' +
+'      <SRS>EPSG:2786</SRS>' +
+'      <SRS>EPSG:2787</SRS>' +
+'      <SRS>EPSG:2788</SRS>' +
+'      <SRS>EPSG:2789</SRS>' +
+'      <SRS>EPSG:2790</SRS>' +
+'      <SRS>EPSG:2791</SRS>' +
+'      <SRS>EPSG:2792</SRS>' +
+'      <SRS>EPSG:2793</SRS>' +
+'      <SRS>EPSG:2794</SRS>' +
+'      <SRS>EPSG:2795</SRS>' +
+'      <SRS>EPSG:2796</SRS>' +
+'      <SRS>EPSG:2797</SRS>' +
+'      <SRS>EPSG:2798</SRS>' +
+'      <SRS>EPSG:2799</SRS>' +
+'      <SRS>EPSG:2800</SRS>' +
+'      <SRS>EPSG:2801</SRS>' +
+'      <SRS>EPSG:2802</SRS>' +
+'      <SRS>EPSG:2803</SRS>' +
+'      <SRS>EPSG:2804</SRS>' +
+'      <SRS>EPSG:2805</SRS>' +
+'      <SRS>EPSG:2806</SRS>' +
+'      <SRS>EPSG:2807</SRS>' +
+'      <SRS>EPSG:2808</SRS>' +
+'      <SRS>EPSG:2809</SRS>' +
+'      <SRS>EPSG:2810</SRS>' +
+'      <SRS>EPSG:2811</SRS>' +
+'      <SRS>EPSG:2812</SRS>' +
+'      <SRS>EPSG:2813</SRS>' +
+'      <SRS>EPSG:2814</SRS>' +
+'      <SRS>EPSG:2815</SRS>' +
+'      <SRS>EPSG:2816</SRS>' +
+'      <SRS>EPSG:2817</SRS>' +
+'      <SRS>EPSG:2818</SRS>' +
+'      <SRS>EPSG:2819</SRS>' +
+'      <SRS>EPSG:2820</SRS>' +
+'      <SRS>EPSG:2821</SRS>' +
+'      <SRS>EPSG:2822</SRS>' +
+'      <SRS>EPSG:2823</SRS>' +
+'      <SRS>EPSG:2824</SRS>' +
+'      <SRS>EPSG:2825</SRS>' +
+'      <SRS>EPSG:2826</SRS>' +
+'      <SRS>EPSG:2827</SRS>' +
+'      <SRS>EPSG:2828</SRS>' +
+'      <SRS>EPSG:2829</SRS>' +
+'      <SRS>EPSG:2830</SRS>' +
+'      <SRS>EPSG:2831</SRS>' +
+'      <SRS>EPSG:2832</SRS>' +
+'      <SRS>EPSG:2833</SRS>' +
+'      <SRS>EPSG:2834</SRS>' +
+'      <SRS>EPSG:2835</SRS>' +
+'      <SRS>EPSG:2836</SRS>' +
+'      <SRS>EPSG:2837</SRS>' +
+'      <SRS>EPSG:2838</SRS>' +
+'      <SRS>EPSG:2839</SRS>' +
+'      <SRS>EPSG:2840</SRS>' +
+'      <SRS>EPSG:2841</SRS>' +
+'      <SRS>EPSG:2842</SRS>' +
+'      <SRS>EPSG:2843</SRS>' +
+'      <SRS>EPSG:2844</SRS>' +
+'      <SRS>EPSG:2845</SRS>' +
+'      <SRS>EPSG:2846</SRS>' +
+'      <SRS>EPSG:2847</SRS>' +
+'      <SRS>EPSG:2848</SRS>' +
+'      <SRS>EPSG:2849</SRS>' +
+'      <SRS>EPSG:2850</SRS>' +
+'      <SRS>EPSG:2851</SRS>' +
+'      <SRS>EPSG:2852</SRS>' +
+'      <SRS>EPSG:2853</SRS>' +
+'      <SRS>EPSG:2854</SRS>' +
+'      <SRS>EPSG:2855</SRS>' +
+'      <SRS>EPSG:2856</SRS>' +
+'      <SRS>EPSG:2857</SRS>' +
+'      <SRS>EPSG:2858</SRS>' +
+'      <SRS>EPSG:2859</SRS>' +
+'      <SRS>EPSG:2860</SRS>' +
+'      <SRS>EPSG:2861</SRS>' +
+'      <SRS>EPSG:2862</SRS>' +
+'      <SRS>EPSG:2863</SRS>' +
+'      <SRS>EPSG:2864</SRS>' +
+'      <SRS>EPSG:2865</SRS>' +
+'      <SRS>EPSG:2866</SRS>' +
+'      <SRS>EPSG:2867</SRS>' +
+'      <SRS>EPSG:2868</SRS>' +
+'      <SRS>EPSG:2869</SRS>' +
+'      <SRS>EPSG:2870</SRS>' +
+'      <SRS>EPSG:2871</SRS>' +
+'      <SRS>EPSG:2872</SRS>' +
+'      <SRS>EPSG:2873</SRS>' +
+'      <SRS>EPSG:2874</SRS>' +
+'      <SRS>EPSG:2875</SRS>' +
+'      <SRS>EPSG:2876</SRS>' +
+'      <SRS>EPSG:2877</SRS>' +
+'      <SRS>EPSG:2878</SRS>' +
+'      <SRS>EPSG:2879</SRS>' +
+'      <SRS>EPSG:2880</SRS>' +
+'      <SRS>EPSG:2881</SRS>' +
+'      <SRS>EPSG:2882</SRS>' +
+'      <SRS>EPSG:2883</SRS>' +
+'      <SRS>EPSG:2884</SRS>' +
+'      <SRS>EPSG:2885</SRS>' +
+'      <SRS>EPSG:2886</SRS>' +
+'      <SRS>EPSG:2887</SRS>' +
+'      <SRS>EPSG:2888</SRS>' +
+'      <SRS>EPSG:2889</SRS>' +
+'      <SRS>EPSG:2890</SRS>' +
+'      <SRS>EPSG:2891</SRS>' +
+'      <SRS>EPSG:2892</SRS>' +
+'      <SRS>EPSG:2893</SRS>' +
+'      <SRS>EPSG:2894</SRS>' +
+'      <SRS>EPSG:2895</SRS>' +
+'      <SRS>EPSG:2896</SRS>' +
+'      <SRS>EPSG:2897</SRS>' +
+'      <SRS>EPSG:2898</SRS>' +
+'      <SRS>EPSG:2899</SRS>' +
+'      <SRS>EPSG:2900</SRS>' +
+'      <SRS>EPSG:2901</SRS>' +
+'      <SRS>EPSG:2902</SRS>' +
+'      <SRS>EPSG:2903</SRS>' +
+'      <SRS>EPSG:2904</SRS>' +
+'      <SRS>EPSG:2905</SRS>' +
+'      <SRS>EPSG:2906</SRS>' +
+'      <SRS>EPSG:2907</SRS>' +
+'      <SRS>EPSG:2908</SRS>' +
+'      <SRS>EPSG:2909</SRS>' +
+'      <SRS>EPSG:2910</SRS>' +
+'      <SRS>EPSG:2911</SRS>' +
+'      <SRS>EPSG:2912</SRS>' +
+'      <SRS>EPSG:2913</SRS>' +
+'      <SRS>EPSG:2914</SRS>' +
+'      <SRS>EPSG:2915</SRS>' +
+'      <SRS>EPSG:2916</SRS>' +
+'      <SRS>EPSG:2917</SRS>' +
+'      <SRS>EPSG:2918</SRS>' +
+'      <SRS>EPSG:2919</SRS>' +
+'      <SRS>EPSG:2920</SRS>' +
+'      <SRS>EPSG:2921</SRS>' +
+'      <SRS>EPSG:2922</SRS>' +
+'      <SRS>EPSG:2923</SRS>' +
+'      <SRS>EPSG:2924</SRS>' +
+'      <SRS>EPSG:2925</SRS>' +
+'      <SRS>EPSG:2926</SRS>' +
+'      <SRS>EPSG:2927</SRS>' +
+'      <SRS>EPSG:2928</SRS>' +
+'      <SRS>EPSG:2929</SRS>' +
+'      <SRS>EPSG:2930</SRS>' +
+'      <SRS>EPSG:2931</SRS>' +
+'      <SRS>EPSG:2932</SRS>' +
+'      <SRS>EPSG:2933</SRS>' +
+'      <SRS>EPSG:2934</SRS>' +
+'      <SRS>EPSG:2935</SRS>' +
+'      <SRS>EPSG:2936</SRS>' +
+'      <SRS>EPSG:2937</SRS>' +
+'      <SRS>EPSG:2938</SRS>' +
+'      <SRS>EPSG:2939</SRS>' +
+'      <SRS>EPSG:2940</SRS>' +
+'      <SRS>EPSG:2941</SRS>' +
+'      <SRS>EPSG:2942</SRS>' +
+'      <SRS>EPSG:2943</SRS>' +
+'      <SRS>EPSG:2944</SRS>' +
+'      <SRS>EPSG:2945</SRS>' +
+'      <SRS>EPSG:2946</SRS>' +
+'      <SRS>EPSG:2947</SRS>' +
+'      <SRS>EPSG:2948</SRS>' +
+'      <SRS>EPSG:2949</SRS>' +
+'      <SRS>EPSG:2950</SRS>' +
+'      <SRS>EPSG:2951</SRS>' +
+'      <SRS>EPSG:2952</SRS>' +
+'      <SRS>EPSG:2953</SRS>' +
+'      <SRS>EPSG:2954</SRS>' +
+'      <SRS>EPSG:2955</SRS>' +
+'      <SRS>EPSG:2956</SRS>' +
+'      <SRS>EPSG:2957</SRS>' +
+'      <SRS>EPSG:2958</SRS>' +
+'      <SRS>EPSG:2959</SRS>' +
+'      <SRS>EPSG:2960</SRS>' +
+'      <SRS>EPSG:2961</SRS>' +
+'      <SRS>EPSG:2962</SRS>' +
+'      <SRS>EPSG:2963</SRS>' +
+'      <SRS>EPSG:2964</SRS>' +
+'      <SRS>EPSG:2965</SRS>' +
+'      <SRS>EPSG:2966</SRS>' +
+'      <SRS>EPSG:2967</SRS>' +
+'      <SRS>EPSG:2968</SRS>' +
+'      <SRS>EPSG:2969</SRS>' +
+'      <SRS>EPSG:2970</SRS>' +
+'      <SRS>EPSG:2971</SRS>' +
+'      <SRS>EPSG:2972</SRS>' +
+'      <SRS>EPSG:2973</SRS>' +
+'      <SRS>EPSG:2975</SRS>' +
+'      <SRS>EPSG:2976</SRS>' +
+'      <SRS>EPSG:2977</SRS>' +
+'      <SRS>EPSG:2978</SRS>' +
+'      <SRS>EPSG:2979</SRS>' +
+'      <SRS>EPSG:2980</SRS>' +
+'      <SRS>EPSG:2981</SRS>' +
+'      <SRS>EPSG:2982</SRS>' +
+'      <SRS>EPSG:2983</SRS>' +
+'      <SRS>EPSG:2984</SRS>' +
+'      <SRS>EPSG:2985</SRS>' +
+'      <SRS>EPSG:2986</SRS>' +
+'      <SRS>EPSG:2987</SRS>' +
+'      <SRS>EPSG:2988</SRS>' +
+'      <SRS>EPSG:2989</SRS>' +
+'      <SRS>EPSG:2990</SRS>' +
+'      <SRS>EPSG:2991</SRS>' +
+'      <SRS>EPSG:2992</SRS>' +
+'      <SRS>EPSG:2993</SRS>' +
+'      <SRS>EPSG:2994</SRS>' +
+'      <SRS>EPSG:2995</SRS>' +
+'      <SRS>EPSG:2996</SRS>' +
+'      <SRS>EPSG:2997</SRS>' +
+'      <SRS>EPSG:2998</SRS>' +
+'      <SRS>EPSG:2999</SRS>' +
+'      <SRS>EPSG:3000</SRS>' +
+'      <SRS>EPSG:3001</SRS>' +
+'      <SRS>EPSG:3002</SRS>' +
+'      <SRS>EPSG:3003</SRS>' +
+'      <SRS>EPSG:3004</SRS>' +
+'      <SRS>EPSG:3005</SRS>' +
+'      <SRS>EPSG:3006</SRS>' +
+'      <SRS>EPSG:3007</SRS>' +
+'      <SRS>EPSG:3008</SRS>' +
+'      <SRS>EPSG:3009</SRS>' +
+'      <SRS>EPSG:3010</SRS>' +
+'      <SRS>EPSG:3011</SRS>' +
+'      <SRS>EPSG:3012</SRS>' +
+'      <SRS>EPSG:3013</SRS>' +
+'      <SRS>EPSG:3014</SRS>' +
+'      <SRS>EPSG:3015</SRS>' +
+'      <SRS>EPSG:3016</SRS>' +
+'      <SRS>EPSG:3017</SRS>' +
+'      <SRS>EPSG:3018</SRS>' +
+'      <SRS>EPSG:3019</SRS>' +
+'      <SRS>EPSG:3020</SRS>' +
+'      <SRS>EPSG:3021</SRS>' +
+'      <SRS>EPSG:3022</SRS>' +
+'      <SRS>EPSG:3023</SRS>' +
+'      <SRS>EPSG:3024</SRS>' +
+'      <SRS>EPSG:3025</SRS>' +
+'      <SRS>EPSG:3026</SRS>' +
+'      <SRS>EPSG:3027</SRS>' +
+'      <SRS>EPSG:3028</SRS>' +
+'      <SRS>EPSG:3029</SRS>' +
+'      <SRS>EPSG:3030</SRS>' +
+'      <SRS>EPSG:3031</SRS>' +
+'      <SRS>EPSG:3032</SRS>' +
+'      <SRS>EPSG:3033</SRS>' +
+'      <SRS>EPSG:3034</SRS>' +
+'      <SRS>EPSG:3035</SRS>' +
+'      <SRS>EPSG:3036</SRS>' +
+'      <SRS>EPSG:3037</SRS>' +
+'      <SRS>EPSG:3038</SRS>' +
+'      <SRS>EPSG:3039</SRS>' +
+'      <SRS>EPSG:3040</SRS>' +
+'      <SRS>EPSG:3041</SRS>' +
+'      <SRS>EPSG:3042</SRS>' +
+'      <SRS>EPSG:3043</SRS>' +
+'      <SRS>EPSG:3044</SRS>' +
+'      <SRS>EPSG:3045</SRS>' +
+'      <SRS>EPSG:3046</SRS>' +
+'      <SRS>EPSG:3047</SRS>' +
+'      <SRS>EPSG:3048</SRS>' +
+'      <SRS>EPSG:3049</SRS>' +
+'      <SRS>EPSG:3050</SRS>' +
+'      <SRS>EPSG:3051</SRS>' +
+'      <SRS>EPSG:3052</SRS>' +
+'      <SRS>EPSG:3053</SRS>' +
+'      <SRS>EPSG:3054</SRS>' +
+'      <SRS>EPSG:3055</SRS>' +
+'      <SRS>EPSG:3056</SRS>' +
+'      <SRS>EPSG:3057</SRS>' +
+'      <SRS>EPSG:3058</SRS>' +
+'      <SRS>EPSG:3059</SRS>' +
+'      <SRS>EPSG:3060</SRS>' +
+'      <SRS>EPSG:3061</SRS>' +
+'      <SRS>EPSG:3062</SRS>' +
+'      <SRS>EPSG:3063</SRS>' +
+'      <SRS>EPSG:3064</SRS>' +
+'      <SRS>EPSG:3065</SRS>' +
+'      <SRS>EPSG:3066</SRS>' +
+'      <SRS>EPSG:3067</SRS>' +
+'      <SRS>EPSG:3068</SRS>' +
+'      <SRS>EPSG:3069</SRS>' +
+'      <SRS>EPSG:3070</SRS>' +
+'      <SRS>EPSG:3071</SRS>' +
+'      <SRS>EPSG:3072</SRS>' +
+'      <SRS>EPSG:3073</SRS>' +
+'      <SRS>EPSG:3074</SRS>' +
+'      <SRS>EPSG:3075</SRS>' +
+'      <SRS>EPSG:3076</SRS>' +
+'      <SRS>EPSG:3077</SRS>' +
+'      <SRS>EPSG:3078</SRS>' +
+'      <SRS>EPSG:3079</SRS>' +
+'      <SRS>EPSG:3080</SRS>' +
+'      <SRS>EPSG:3081</SRS>' +
+'      <SRS>EPSG:3082</SRS>' +
+'      <SRS>EPSG:3083</SRS>' +
+'      <SRS>EPSG:3084</SRS>' +
+'      <SRS>EPSG:3085</SRS>' +
+'      <SRS>EPSG:3086</SRS>' +
+'      <SRS>EPSG:3087</SRS>' +
+'      <SRS>EPSG:3088</SRS>' +
+'      <SRS>EPSG:3089</SRS>' +
+'      <SRS>EPSG:3090</SRS>' +
+'      <SRS>EPSG:3091</SRS>' +
+'      <SRS>EPSG:3092</SRS>' +
+'      <SRS>EPSG:3093</SRS>' +
+'      <SRS>EPSG:3094</SRS>' +
+'      <SRS>EPSG:3095</SRS>' +
+'      <SRS>EPSG:3096</SRS>' +
+'      <SRS>EPSG:3097</SRS>' +
+'      <SRS>EPSG:3098</SRS>' +
+'      <SRS>EPSG:3099</SRS>' +
+'      <SRS>EPSG:3100</SRS>' +
+'      <SRS>EPSG:3101</SRS>' +
+'      <SRS>EPSG:3102</SRS>' +
+'      <SRS>EPSG:3103</SRS>' +
+'      <SRS>EPSG:3104</SRS>' +
+'      <SRS>EPSG:3105</SRS>' +
+'      <SRS>EPSG:3106</SRS>' +
+'      <SRS>EPSG:3107</SRS>' +
+'      <SRS>EPSG:3108</SRS>' +
+'      <SRS>EPSG:3109</SRS>' +
+'      <SRS>EPSG:3110</SRS>' +
+'      <SRS>EPSG:3111</SRS>' +
+'      <SRS>EPSG:3112</SRS>' +
+'      <SRS>EPSG:3113</SRS>' +
+'      <SRS>EPSG:3114</SRS>' +
+'      <SRS>EPSG:3115</SRS>' +
+'      <SRS>EPSG:3116</SRS>' +
+'      <SRS>EPSG:3117</SRS>' +
+'      <SRS>EPSG:3118</SRS>' +
+'      <SRS>EPSG:3119</SRS>' +
+'      <SRS>EPSG:3120</SRS>' +
+'      <SRS>EPSG:3121</SRS>' +
+'      <SRS>EPSG:3122</SRS>' +
+'      <SRS>EPSG:3123</SRS>' +
+'      <SRS>EPSG:3124</SRS>' +
+'      <SRS>EPSG:3125</SRS>' +
+'      <SRS>EPSG:3126</SRS>' +
+'      <SRS>EPSG:3127</SRS>' +
+'      <SRS>EPSG:3128</SRS>' +
+'      <SRS>EPSG:3129</SRS>' +
+'      <SRS>EPSG:3130</SRS>' +
+'      <SRS>EPSG:3131</SRS>' +
+'      <SRS>EPSG:3132</SRS>' +
+'      <SRS>EPSG:3133</SRS>' +
+'      <SRS>EPSG:3134</SRS>' +
+'      <SRS>EPSG:3135</SRS>' +
+'      <SRS>EPSG:3136</SRS>' +
+'      <SRS>EPSG:3137</SRS>' +
+'      <SRS>EPSG:3138</SRS>' +
+'      <SRS>EPSG:3139</SRS>' +
+'      <SRS>EPSG:3140</SRS>' +
+'      <SRS>EPSG:3141</SRS>' +
+'      <SRS>EPSG:3142</SRS>' +
+'      <SRS>EPSG:3143</SRS>' +
+'      <SRS>EPSG:3144</SRS>' +
+'      <SRS>EPSG:3145</SRS>' +
+'      <SRS>EPSG:3146</SRS>' +
+'      <SRS>EPSG:3147</SRS>' +
+'      <SRS>EPSG:3148</SRS>' +
+'      <SRS>EPSG:3149</SRS>' +
+'      <SRS>EPSG:3150</SRS>' +
+'      <SRS>EPSG:3151</SRS>' +
+'      <SRS>EPSG:3152</SRS>' +
+'      <SRS>EPSG:3153</SRS>' +
+'      <SRS>EPSG:3154</SRS>' +
+'      <SRS>EPSG:3155</SRS>' +
+'      <SRS>EPSG:3156</SRS>' +
+'      <SRS>EPSG:3157</SRS>' +
+'      <SRS>EPSG:3158</SRS>' +
+'      <SRS>EPSG:3159</SRS>' +
+'      <SRS>EPSG:3160</SRS>' +
+'      <SRS>EPSG:3161</SRS>' +
+'      <SRS>EPSG:3162</SRS>' +
+'      <SRS>EPSG:3163</SRS>' +
+'      <SRS>EPSG:3164</SRS>' +
+'      <SRS>EPSG:3165</SRS>' +
+'      <SRS>EPSG:3166</SRS>' +
+'      <SRS>EPSG:3167</SRS>' +
+'      <SRS>EPSG:3168</SRS>' +
+'      <SRS>EPSG:3169</SRS>' +
+'      <SRS>EPSG:3170</SRS>' +
+'      <SRS>EPSG:3171</SRS>' +
+'      <SRS>EPSG:3172</SRS>' +
+'      <SRS>EPSG:3173</SRS>' +
+'      <SRS>EPSG:3174</SRS>' +
+'      <SRS>EPSG:3175</SRS>' +
+'      <SRS>EPSG:3176</SRS>' +
+'      <SRS>EPSG:3177</SRS>' +
+'      <SRS>EPSG:3178</SRS>' +
+'      <SRS>EPSG:3179</SRS>' +
+'      <SRS>EPSG:3180</SRS>' +
+'      <SRS>EPSG:3181</SRS>' +
+'      <SRS>EPSG:3182</SRS>' +
+'      <SRS>EPSG:3183</SRS>' +
+'      <SRS>EPSG:3184</SRS>' +
+'      <SRS>EPSG:3185</SRS>' +
+'      <SRS>EPSG:3186</SRS>' +
+'      <SRS>EPSG:3187</SRS>' +
+'      <SRS>EPSG:3188</SRS>' +
+'      <SRS>EPSG:3189</SRS>' +
+'      <SRS>EPSG:3190</SRS>' +
+'      <SRS>EPSG:3191</SRS>' +
+'      <SRS>EPSG:3192</SRS>' +
+'      <SRS>EPSG:3193</SRS>' +
+'      <SRS>EPSG:3194</SRS>' +
+'      <SRS>EPSG:3195</SRS>' +
+'      <SRS>EPSG:3196</SRS>' +
+'      <SRS>EPSG:3197</SRS>' +
+'      <SRS>EPSG:3198</SRS>' +
+'      <SRS>EPSG:3199</SRS>' +
+'      <SRS>EPSG:3200</SRS>' +
+'      <SRS>EPSG:3201</SRS>' +
+'      <SRS>EPSG:3202</SRS>' +
+'      <SRS>EPSG:3203</SRS>' +
+'      <SRS>EPSG:3204</SRS>' +
+'      <SRS>EPSG:3205</SRS>' +
+'      <SRS>EPSG:3206</SRS>' +
+'      <SRS>EPSG:3207</SRS>' +
+'      <SRS>EPSG:3208</SRS>' +
+'      <SRS>EPSG:3209</SRS>' +
+'      <SRS>EPSG:3210</SRS>' +
+'      <SRS>EPSG:3211</SRS>' +
+'      <SRS>EPSG:3212</SRS>' +
+'      <SRS>EPSG:3213</SRS>' +
+'      <SRS>EPSG:3214</SRS>' +
+'      <SRS>EPSG:3215</SRS>' +
+'      <SRS>EPSG:3216</SRS>' +
+'      <SRS>EPSG:3217</SRS>' +
+'      <SRS>EPSG:3218</SRS>' +
+'      <SRS>EPSG:3219</SRS>' +
+'      <SRS>EPSG:3220</SRS>' +
+'      <SRS>EPSG:3221</SRS>' +
+'      <SRS>EPSG:3222</SRS>' +
+'      <SRS>EPSG:3223</SRS>' +
+'      <SRS>EPSG:3224</SRS>' +
+'      <SRS>EPSG:3225</SRS>' +
+'      <SRS>EPSG:3226</SRS>' +
+'      <SRS>EPSG:3227</SRS>' +
+'      <SRS>EPSG:3228</SRS>' +
+'      <SRS>EPSG:3229</SRS>' +
+'      <SRS>EPSG:3230</SRS>' +
+'      <SRS>EPSG:3231</SRS>' +
+'      <SRS>EPSG:3232</SRS>' +
+'      <SRS>EPSG:3233</SRS>' +
+'      <SRS>EPSG:3234</SRS>' +
+'      <SRS>EPSG:3235</SRS>' +
+'      <SRS>EPSG:3236</SRS>' +
+'      <SRS>EPSG:3237</SRS>' +
+'      <SRS>EPSG:3238</SRS>' +
+'      <SRS>EPSG:3239</SRS>' +
+'      <SRS>EPSG:3240</SRS>' +
+'      <SRS>EPSG:3241</SRS>' +
+'      <SRS>EPSG:3242</SRS>' +
+'      <SRS>EPSG:3243</SRS>' +
+'      <SRS>EPSG:3244</SRS>' +
+'      <SRS>EPSG:3245</SRS>' +
+'      <SRS>EPSG:3246</SRS>' +
+'      <SRS>EPSG:3247</SRS>' +
+'      <SRS>EPSG:3248</SRS>' +
+'      <SRS>EPSG:3249</SRS>' +
+'      <SRS>EPSG:3250</SRS>' +
+'      <SRS>EPSG:3251</SRS>' +
+'      <SRS>EPSG:3252</SRS>' +
+'      <SRS>EPSG:3253</SRS>' +
+'      <SRS>EPSG:3254</SRS>' +
+'      <SRS>EPSG:3255</SRS>' +
+'      <SRS>EPSG:3256</SRS>' +
+'      <SRS>EPSG:3257</SRS>' +
+'      <SRS>EPSG:3258</SRS>' +
+'      <SRS>EPSG:3259</SRS>' +
+'      <SRS>EPSG:3260</SRS>' +
+'      <SRS>EPSG:3261</SRS>' +
+'      <SRS>EPSG:3262</SRS>' +
+'      <SRS>EPSG:3263</SRS>' +
+'      <SRS>EPSG:3264</SRS>' +
+'      <SRS>EPSG:3265</SRS>' +
+'      <SRS>EPSG:3266</SRS>' +
+'      <SRS>EPSG:3267</SRS>' +
+'      <SRS>EPSG:3268</SRS>' +
+'      <SRS>EPSG:3269</SRS>' +
+'      <SRS>EPSG:3270</SRS>' +
+'      <SRS>EPSG:3271</SRS>' +
+'      <SRS>EPSG:3272</SRS>' +
+'      <SRS>EPSG:3273</SRS>' +
+'      <SRS>EPSG:3274</SRS>' +
+'      <SRS>EPSG:3275</SRS>' +
+'      <SRS>EPSG:3276</SRS>' +
+'      <SRS>EPSG:3277</SRS>' +
+'      <SRS>EPSG:3278</SRS>' +
+'      <SRS>EPSG:3279</SRS>' +
+'      <SRS>EPSG:3280</SRS>' +
+'      <SRS>EPSG:3281</SRS>' +
+'      <SRS>EPSG:3282</SRS>' +
+'      <SRS>EPSG:3283</SRS>' +
+'      <SRS>EPSG:3284</SRS>' +
+'      <SRS>EPSG:3285</SRS>' +
+'      <SRS>EPSG:3286</SRS>' +
+'      <SRS>EPSG:3287</SRS>' +
+'      <SRS>EPSG:3288</SRS>' +
+'      <SRS>EPSG:3289</SRS>' +
+'      <SRS>EPSG:3290</SRS>' +
+'      <SRS>EPSG:3291</SRS>' +
+'      <SRS>EPSG:3292</SRS>' +
+'      <SRS>EPSG:3293</SRS>' +
+'      <SRS>EPSG:3294</SRS>' +
+'      <SRS>EPSG:3295</SRS>' +
+'      <SRS>EPSG:3296</SRS>' +
+'      <SRS>EPSG:3297</SRS>' +
+'      <SRS>EPSG:3298</SRS>' +
+'      <SRS>EPSG:3299</SRS>' +
+'      <SRS>EPSG:3300</SRS>' +
+'      <SRS>EPSG:3301</SRS>' +
+'      <SRS>EPSG:3302</SRS>' +
+'      <SRS>EPSG:3303</SRS>' +
+'      <SRS>EPSG:3304</SRS>' +
+'      <SRS>EPSG:3305</SRS>' +
+'      <SRS>EPSG:3306</SRS>' +
+'      <SRS>EPSG:3307</SRS>' +
+'      <SRS>EPSG:3308</SRS>' +
+'      <SRS>EPSG:3309</SRS>' +
+'      <SRS>EPSG:3310</SRS>' +
+'      <SRS>EPSG:3311</SRS>' +
+'      <SRS>EPSG:3312</SRS>' +
+'      <SRS>EPSG:3313</SRS>' +
+'      <SRS>EPSG:3314</SRS>' +
+'      <SRS>EPSG:3315</SRS>' +
+'      <SRS>EPSG:3316</SRS>' +
+'      <SRS>EPSG:3317</SRS>' +
+'      <SRS>EPSG:3318</SRS>' +
+'      <SRS>EPSG:3319</SRS>' +
+'      <SRS>EPSG:3320</SRS>' +
+'      <SRS>EPSG:3321</SRS>' +
+'      <SRS>EPSG:3322</SRS>' +
+'      <SRS>EPSG:3323</SRS>' +
+'      <SRS>EPSG:3324</SRS>' +
+'      <SRS>EPSG:3325</SRS>' +
+'      <SRS>EPSG:3326</SRS>' +
+'      <SRS>EPSG:3327</SRS>' +
+'      <SRS>EPSG:3328</SRS>' +
+'      <SRS>EPSG:3329</SRS>' +
+'      <SRS>EPSG:3330</SRS>' +
+'      <SRS>EPSG:3331</SRS>' +
+'      <SRS>EPSG:3332</SRS>' +
+'      <SRS>EPSG:3333</SRS>' +
+'      <SRS>EPSG:3334</SRS>' +
+'      <SRS>EPSG:3335</SRS>' +
+'      <SRS>EPSG:3336</SRS>' +
+'      <SRS>EPSG:3337</SRS>' +
+'      <SRS>EPSG:3338</SRS>' +
+'      <SRS>EPSG:3339</SRS>' +
+'      <SRS>EPSG:3340</SRS>' +
+'      <SRS>EPSG:3341</SRS>' +
+'      <SRS>EPSG:3342</SRS>' +
+'      <SRS>EPSG:3343</SRS>' +
+'      <SRS>EPSG:3344</SRS>' +
+'      <SRS>EPSG:3345</SRS>' +
+'      <SRS>EPSG:3346</SRS>' +
+'      <SRS>EPSG:3347</SRS>' +
+'      <SRS>EPSG:3348</SRS>' +
+'      <SRS>EPSG:3349</SRS>' +
+'      <SRS>EPSG:3350</SRS>' +
+'      <SRS>EPSG:3351</SRS>' +
+'      <SRS>EPSG:3352</SRS>' +
+'      <SRS>EPSG:3353</SRS>' +
+'      <SRS>EPSG:3354</SRS>' +
+'      <SRS>EPSG:3355</SRS>' +
+'      <SRS>EPSG:3356</SRS>' +
+'      <SRS>EPSG:3357</SRS>' +
+'      <SRS>EPSG:3358</SRS>' +
+'      <SRS>EPSG:3359</SRS>' +
+'      <SRS>EPSG:3360</SRS>' +
+'      <SRS>EPSG:3361</SRS>' +
+'      <SRS>EPSG:3362</SRS>' +
+'      <SRS>EPSG:3363</SRS>' +
+'      <SRS>EPSG:3364</SRS>' +
+'      <SRS>EPSG:3365</SRS>' +
+'      <SRS>EPSG:3366</SRS>' +
+'      <SRS>EPSG:3367</SRS>' +
+'      <SRS>EPSG:3368</SRS>' +
+'      <SRS>EPSG:3369</SRS>' +
+'      <SRS>EPSG:3370</SRS>' +
+'      <SRS>EPSG:3371</SRS>' +
+'      <SRS>EPSG:3372</SRS>' +
+'      <SRS>EPSG:3373</SRS>' +
+'      <SRS>EPSG:3374</SRS>' +
+'      <SRS>EPSG:3375</SRS>' +
+'      <SRS>EPSG:3376</SRS>' +
+'      <SRS>EPSG:3377</SRS>' +
+'      <SRS>EPSG:3378</SRS>' +
+'      <SRS>EPSG:3379</SRS>' +
+'      <SRS>EPSG:3380</SRS>' +
+'      <SRS>EPSG:3381</SRS>' +
+'      <SRS>EPSG:3382</SRS>' +
+'      <SRS>EPSG:3383</SRS>' +
+'      <SRS>EPSG:3384</SRS>' +
+'      <SRS>EPSG:3385</SRS>' +
+'      <SRS>EPSG:3386</SRS>' +
+'      <SRS>EPSG:3387</SRS>' +
+'      <SRS>EPSG:3388</SRS>' +
+'      <SRS>EPSG:3389</SRS>' +
+'      <SRS>EPSG:3390</SRS>' +
+'      <SRS>EPSG:3391</SRS>' +
+'      <SRS>EPSG:3392</SRS>' +
+'      <SRS>EPSG:3393</SRS>' +
+'      <SRS>EPSG:3394</SRS>' +
+'      <SRS>EPSG:3395</SRS>' +
+'      <SRS>EPSG:3396</SRS>' +
+'      <SRS>EPSG:3397</SRS>' +
+'      <SRS>EPSG:3398</SRS>' +
+'      <SRS>EPSG:3399</SRS>' +
+'      <SRS>EPSG:3400</SRS>' +
+'      <SRS>EPSG:3401</SRS>' +
+'      <SRS>EPSG:3402</SRS>' +
+'      <SRS>EPSG:3403</SRS>' +
+'      <SRS>EPSG:3404</SRS>' +
+'      <SRS>EPSG:3405</SRS>' +
+'      <SRS>EPSG:3406</SRS>' +
+'      <SRS>EPSG:3407</SRS>' +
+'      <SRS>EPSG:3408</SRS>' +
+'      <SRS>EPSG:3409</SRS>' +
+'      <SRS>EPSG:3410</SRS>' +
+'      <SRS>EPSG:3411</SRS>' +
+'      <SRS>EPSG:3412</SRS>' +
+'      <SRS>EPSG:3413</SRS>' +
+'      <SRS>EPSG:3414</SRS>' +
+'      <SRS>EPSG:3415</SRS>' +
+'      <SRS>EPSG:3416</SRS>' +
+'      <SRS>EPSG:3417</SRS>' +
+'      <SRS>EPSG:3418</SRS>' +
+'      <SRS>EPSG:3419</SRS>' +
+'      <SRS>EPSG:3420</SRS>' +
+'      <SRS>EPSG:3421</SRS>' +
+'      <SRS>EPSG:3422</SRS>' +
+'      <SRS>EPSG:3423</SRS>' +
+'      <SRS>EPSG:3424</SRS>' +
+'      <SRS>EPSG:3425</SRS>' +
+'      <SRS>EPSG:3426</SRS>' +
+'      <SRS>EPSG:3427</SRS>' +
+'      <SRS>EPSG:3428</SRS>' +
+'      <SRS>EPSG:3429</SRS>' +
+'      <SRS>EPSG:3430</SRS>' +
+'      <SRS>EPSG:3431</SRS>' +
+'      <SRS>EPSG:3432</SRS>' +
+'      <SRS>EPSG:3433</SRS>' +
+'      <SRS>EPSG:3434</SRS>' +
+'      <SRS>EPSG:3435</SRS>' +
+'      <SRS>EPSG:3436</SRS>' +
+'      <SRS>EPSG:3437</SRS>' +
+'      <SRS>EPSG:3438</SRS>' +
+'      <SRS>EPSG:3439</SRS>' +
+'      <SRS>EPSG:3440</SRS>' +
+'      <SRS>EPSG:3441</SRS>' +
+'      <SRS>EPSG:3442</SRS>' +
+'      <SRS>EPSG:3443</SRS>' +
+'      <SRS>EPSG:3444</SRS>' +
+'      <SRS>EPSG:3445</SRS>' +
+'      <SRS>EPSG:3446</SRS>' +
+'      <SRS>EPSG:3447</SRS>' +
+'      <SRS>EPSG:3448</SRS>' +
+'      <SRS>EPSG:3449</SRS>' +
+'      <SRS>EPSG:3450</SRS>' +
+'      <SRS>EPSG:3451</SRS>' +
+'      <SRS>EPSG:3452</SRS>' +
+'      <SRS>EPSG:3453</SRS>' +
+'      <SRS>EPSG:3454</SRS>' +
+'      <SRS>EPSG:3455</SRS>' +
+'      <SRS>EPSG:3456</SRS>' +
+'      <SRS>EPSG:3457</SRS>' +
+'      <SRS>EPSG:3458</SRS>' +
+'      <SRS>EPSG:3459</SRS>' +
+'      <SRS>EPSG:3460</SRS>' +
+'      <SRS>EPSG:3461</SRS>' +
+'      <SRS>EPSG:3462</SRS>' +
+'      <SRS>EPSG:3463</SRS>' +
+'      <SRS>EPSG:3464</SRS>' +
+'      <SRS>EPSG:3560</SRS>' +
+'      <SRS>EPSG:3561</SRS>' +
+'      <SRS>EPSG:3562</SRS>' +
+'      <SRS>EPSG:3563</SRS>' +
+'      <SRS>EPSG:3564</SRS>' +
+'      <SRS>EPSG:3565</SRS>' +
+'      <SRS>EPSG:3566</SRS>' +
+'      <SRS>EPSG:3567</SRS>' +
+'      <SRS>EPSG:3568</SRS>' +
+'      <SRS>EPSG:3569</SRS>' +
+'      <SRS>EPSG:3570</SRS>' +
+'      <SRS>EPSG:3571</SRS>' +
+'      <SRS>EPSG:3572</SRS>' +
+'      <SRS>EPSG:3573</SRS>' +
+'      <SRS>EPSG:3574</SRS>' +
+'      <SRS>EPSG:3575</SRS>' +
+'      <SRS>EPSG:3576</SRS>' +
+'      <SRS>EPSG:3577</SRS>' +
+'      <SRS>EPSG:3920</SRS>' +
+'      <SRS>EPSG:3991</SRS>' +
+'      <SRS>EPSG:3992</SRS>' +
+'      <SRS>EPSG:3993</SRS>' +
+'      <SRS>EPSG:4001</SRS>' +
+'      <SRS>EPSG:4002</SRS>' +
+'      <SRS>EPSG:4003</SRS>' +
+'      <SRS>EPSG:4004</SRS>' +
+'      <SRS>EPSG:4005</SRS>' +
+'      <SRS>EPSG:4006</SRS>' +
+'      <SRS>EPSG:4007</SRS>' +
+'      <SRS>EPSG:4008</SRS>' +
+'      <SRS>EPSG:4009</SRS>' +
+'      <SRS>EPSG:4010</SRS>' +
+'      <SRS>EPSG:4011</SRS>' +
+'      <SRS>EPSG:4012</SRS>' +
+'      <SRS>EPSG:4013</SRS>' +
+'      <SRS>EPSG:4014</SRS>' +
+'      <SRS>EPSG:4015</SRS>' +
+'      <SRS>EPSG:4016</SRS>' +
+'      <SRS>EPSG:4018</SRS>' +
+'      <SRS>EPSG:4019</SRS>' +
+'      <SRS>EPSG:4020</SRS>' +
+'      <SRS>EPSG:4021</SRS>' +
+'      <SRS>EPSG:4022</SRS>' +
+'      <SRS>EPSG:4024</SRS>' +
+'      <SRS>EPSG:4025</SRS>' +
+'      <SRS>EPSG:4027</SRS>' +
+'      <SRS>EPSG:4028</SRS>' +
+'      <SRS>EPSG:4029</SRS>' +
+'      <SRS>EPSG:4030</SRS>' +
+'      <SRS>EPSG:4031</SRS>' +
+'      <SRS>EPSG:4032</SRS>' +
+'      <SRS>EPSG:4033</SRS>' +
+'      <SRS>EPSG:4034</SRS>' +
+'      <SRS>EPSG:4035</SRS>' +
+'      <SRS>EPSG:4036</SRS>' +
+'      <SRS>EPSG:4041</SRS>' +
+'      <SRS>EPSG:4042</SRS>' +
+'      <SRS>EPSG:4043</SRS>' +
+'      <SRS>EPSG:4044</SRS>' +
+'      <SRS>EPSG:4045</SRS>' +
+'      <SRS>EPSG:4047</SRS>' +
+'      <SRS>EPSG:4052</SRS>' +
+'      <SRS>EPSG:4053</SRS>' +
+'      <SRS>EPSG:4054</SRS>' +
+'      <SRS>EPSG:4120</SRS>' +
+'      <SRS>EPSG:4121</SRS>' +
+'      <SRS>EPSG:4122</SRS>' +
+'      <SRS>EPSG:4123</SRS>' +
+'      <SRS>EPSG:4124</SRS>' +
+'      <SRS>EPSG:4125</SRS>' +
+'      <SRS>EPSG:4126</SRS>' +
+'      <SRS>EPSG:4127</SRS>' +
+'      <SRS>EPSG:4128</SRS>' +
+'      <SRS>EPSG:4129</SRS>' +
+'      <SRS>EPSG:4130</SRS>' +
+'      <SRS>EPSG:4131</SRS>' +
+'      <SRS>EPSG:4132</SRS>' +
+'      <SRS>EPSG:4133</SRS>' +
+'      <SRS>EPSG:4134</SRS>' +
+'      <SRS>EPSG:4135</SRS>' +
+'      <SRS>EPSG:4136</SRS>' +
+'      <SRS>EPSG:4137</SRS>' +
+'      <SRS>EPSG:4138</SRS>' +
+'      <SRS>EPSG:4139</SRS>' +
+'      <SRS>EPSG:4140</SRS>' +
+'      <SRS>EPSG:4141</SRS>' +
+'      <SRS>EPSG:4142</SRS>' +
+'      <SRS>EPSG:4143</SRS>' +
+'      <SRS>EPSG:4144</SRS>' +
+'      <SRS>EPSG:4145</SRS>' +
+'      <SRS>EPSG:4146</SRS>' +
+'      <SRS>EPSG:4147</SRS>' +
+'      <SRS>EPSG:4148</SRS>' +
+'      <SRS>EPSG:4149</SRS>' +
+'      <SRS>EPSG:4150</SRS>' +
+'      <SRS>EPSG:4151</SRS>' +
+'      <SRS>EPSG:4152</SRS>' +
+'      <SRS>EPSG:4153</SRS>' +
+'      <SRS>EPSG:4154</SRS>' +
+'      <SRS>EPSG:4155</SRS>' +
+'      <SRS>EPSG:4156</SRS>' +
+'      <SRS>EPSG:4157</SRS>' +
+'      <SRS>EPSG:4158</SRS>' +
+'      <SRS>EPSG:4159</SRS>' +
+'      <SRS>EPSG:4160</SRS>' +
+'      <SRS>EPSG:4161</SRS>' +
+'      <SRS>EPSG:4162</SRS>' +
+'      <SRS>EPSG:4163</SRS>' +
+'      <SRS>EPSG:4164</SRS>' +
+'      <SRS>EPSG:4165</SRS>' +
+'      <SRS>EPSG:4166</SRS>' +
+'      <SRS>EPSG:4167</SRS>' +
+'      <SRS>EPSG:4168</SRS>' +
+'      <SRS>EPSG:4169</SRS>' +
+'      <SRS>EPSG:4170</SRS>' +
+'      <SRS>EPSG:4171</SRS>' +
+'      <SRS>EPSG:4172</SRS>' +
+'      <SRS>EPSG:4173</SRS>' +
+'      <SRS>EPSG:4174</SRS>' +
+'      <SRS>EPSG:4175</SRS>' +
+'      <SRS>EPSG:4176</SRS>' +
+'      <SRS>EPSG:4178</SRS>' +
+'      <SRS>EPSG:4179</SRS>' +
+'      <SRS>EPSG:4180</SRS>' +
+'      <SRS>EPSG:4181</SRS>' +
+'      <SRS>EPSG:4182</SRS>' +
+'      <SRS>EPSG:4183</SRS>' +
+'      <SRS>EPSG:4184</SRS>' +
+'      <SRS>EPSG:4185</SRS>' +
+'      <SRS>EPSG:4188</SRS>' +
+'      <SRS>EPSG:4189</SRS>' +
+'      <SRS>EPSG:4190</SRS>' +
+'      <SRS>EPSG:4191</SRS>' +
+'      <SRS>EPSG:4192</SRS>' +
+'      <SRS>EPSG:4193</SRS>' +
+'      <SRS>EPSG:4194</SRS>' +
+'      <SRS>EPSG:4195</SRS>' +
+'      <SRS>EPSG:4196</SRS>' +
+'      <SRS>EPSG:4197</SRS>' +
+'      <SRS>EPSG:4198</SRS>' +
+'      <SRS>EPSG:4199</SRS>' +
+'      <SRS>EPSG:4200</SRS>' +
+'      <SRS>EPSG:4201</SRS>' +
+'      <SRS>EPSG:4202</SRS>' +
+'      <SRS>EPSG:4203</SRS>' +
+'      <SRS>EPSG:4204</SRS>' +
+'      <SRS>EPSG:4205</SRS>' +
+'      <SRS>EPSG:4206</SRS>' +
+'      <SRS>EPSG:4207</SRS>' +
+'      <SRS>EPSG:4208</SRS>' +
+'      <SRS>EPSG:4209</SRS>' +
+'      <SRS>EPSG:4210</SRS>' +
+'      <SRS>EPSG:4211</SRS>' +
+'      <SRS>EPSG:4212</SRS>' +
+'      <SRS>EPSG:4213</SRS>' +
+'      <SRS>EPSG:4214</SRS>' +
+'      <SRS>EPSG:4215</SRS>' +
+'      <SRS>EPSG:4216</SRS>' +
+'      <SRS>EPSG:4218</SRS>' +
+'      <SRS>EPSG:4219</SRS>' +
+'      <SRS>EPSG:4220</SRS>' +
+'      <SRS>EPSG:4221</SRS>' +
+'      <SRS>EPSG:4222</SRS>' +
+'      <SRS>EPSG:4223</SRS>' +
+'      <SRS>EPSG:4224</SRS>' +
+'      <SRS>EPSG:4225</SRS>' +
+'      <SRS>EPSG:4226</SRS>' +
+'      <SRS>EPSG:4227</SRS>' +
+'      <SRS>EPSG:4228</SRS>' +
+'      <SRS>EPSG:4229</SRS>' +
+'      <SRS>EPSG:4230</SRS>' +
+'      <SRS>EPSG:4231</SRS>' +
+'      <SRS>EPSG:4232</SRS>' +
+'      <SRS>EPSG:4233</SRS>' +
+'      <SRS>EPSG:4234</SRS>' +
+'      <SRS>EPSG:4235</SRS>' +
+'      <SRS>EPSG:4236</SRS>' +
+'      <SRS>EPSG:4237</SRS>' +
+'      <SRS>EPSG:4238</SRS>' +
+'      <SRS>EPSG:4239</SRS>' +
+'      <SRS>EPSG:4240</SRS>' +
+'      <SRS>EPSG:4241</SRS>' +
+'      <SRS>EPSG:4242</SRS>' +
+'      <SRS>EPSG:4243</SRS>' +
+'      <SRS>EPSG:4244</SRS>' +
+'      <SRS>EPSG:4245</SRS>' +
+'      <SRS>EPSG:4246</SRS>' +
+'      <SRS>EPSG:4247</SRS>' +
+'      <SRS>EPSG:4248</SRS>' +
+'      <SRS>EPSG:4249</SRS>' +
+'      <SRS>EPSG:4250</SRS>' +
+'      <SRS>EPSG:4251</SRS>' +
+'      <SRS>EPSG:4252</SRS>' +
+'      <SRS>EPSG:4253</SRS>' +
+'      <SRS>EPSG:4254</SRS>' +
+'      <SRS>EPSG:4255</SRS>' +
+'      <SRS>EPSG:4256</SRS>' +
+'      <SRS>EPSG:4257</SRS>' +
+'      <SRS>EPSG:4258</SRS>' +
+'      <SRS>EPSG:4259</SRS>' +
+'      <SRS>EPSG:4260</SRS>' +
+'      <SRS>EPSG:4261</SRS>' +
+'      <SRS>EPSG:4262</SRS>' +
+'      <SRS>EPSG:4263</SRS>' +
+'      <SRS>EPSG:4264</SRS>' +
+'      <SRS>EPSG:4265</SRS>' +
+'      <SRS>EPSG:4266</SRS>' +
+'      <SRS>EPSG:4267</SRS>' +
+'      <SRS>EPSG:4268</SRS>' +
+'      <SRS>EPSG:4269</SRS>' +
+'      <SRS>EPSG:4270</SRS>' +
+'      <SRS>EPSG:4271</SRS>' +
+'      <SRS>EPSG:4272</SRS>' +
+'      <SRS>EPSG:4273</SRS>' +
+'      <SRS>EPSG:4274</SRS>' +
+'      <SRS>EPSG:4275</SRS>' +
+'      <SRS>EPSG:4276</SRS>' +
+'      <SRS>EPSG:4277</SRS>' +
+'      <SRS>EPSG:4278</SRS>' +
+'      <SRS>EPSG:4279</SRS>' +
+'      <SRS>EPSG:4280</SRS>' +
+'      <SRS>EPSG:4281</SRS>' +
+'      <SRS>EPSG:4282</SRS>' +
+'      <SRS>EPSG:4283</SRS>' +
+'      <SRS>EPSG:4284</SRS>' +
+'      <SRS>EPSG:4285</SRS>' +
+'      <SRS>EPSG:4286</SRS>' +
+'      <SRS>EPSG:4287</SRS>' +
+'      <SRS>EPSG:4288</SRS>' +
+'      <SRS>EPSG:4289</SRS>' +
+'      <SRS>EPSG:4291</SRS>' +
+'      <SRS>EPSG:4292</SRS>' +
+'      <SRS>EPSG:4293</SRS>' +
+'      <SRS>EPSG:4294</SRS>' +
+'      <SRS>EPSG:4295</SRS>' +
+'      <SRS>EPSG:4296</SRS>' +
+'      <SRS>EPSG:4297</SRS>' +
+'      <SRS>EPSG:4298</SRS>' +
+'      <SRS>EPSG:4299</SRS>' +
+'      <SRS>EPSG:4300</SRS>' +
+'      <SRS>EPSG:4301</SRS>' +
+'      <SRS>EPSG:4302</SRS>' +
+'      <SRS>EPSG:4303</SRS>' +
+'      <SRS>EPSG:4304</SRS>' +
+'      <SRS>EPSG:4306</SRS>' +
+'      <SRS>EPSG:4307</SRS>' +
+'      <SRS>EPSG:4308</SRS>' +
+'      <SRS>EPSG:4309</SRS>' +
+'      <SRS>EPSG:4310</SRS>' +
+'      <SRS>EPSG:4311</SRS>' +
+'      <SRS>EPSG:4312</SRS>' +
+'      <SRS>EPSG:4313</SRS>' +
+'      <SRS>EPSG:4314</SRS>' +
+'      <SRS>EPSG:4315</SRS>' +
+'      <SRS>EPSG:4316</SRS>' +
+'      <SRS>EPSG:4317</SRS>' +
+'      <SRS>EPSG:4318</SRS>' +
+'      <SRS>EPSG:4319</SRS>' +
+'      <SRS>EPSG:4322</SRS>' +
+'      <SRS>EPSG:4324</SRS>' +
+'      <SRS>EPSG:4326</SRS>' +
+'      <SRS>EPSG:4327</SRS>' +
+'      <SRS>EPSG:4328</SRS>' +
+'      <SRS>EPSG:4329</SRS>' +
+'      <SRS>EPSG:4330</SRS>' +
+'      <SRS>EPSG:4331</SRS>' +
+'      <SRS>EPSG:4332</SRS>' +
+'      <SRS>EPSG:4333</SRS>' +
+'      <SRS>EPSG:4334</SRS>' +
+'      <SRS>EPSG:4335</SRS>' +
+'      <SRS>EPSG:4336</SRS>' +
+'      <SRS>EPSG:4337</SRS>' +
+'      <SRS>EPSG:4338</SRS>' +
+'      <SRS>EPSG:4339</SRS>' +
+'      <SRS>EPSG:4340</SRS>' +
+'      <SRS>EPSG:4341</SRS>' +
+'      <SRS>EPSG:4342</SRS>' +
+'      <SRS>EPSG:4343</SRS>' +
+'      <SRS>EPSG:4344</SRS>' +
+'      <SRS>EPSG:4345</SRS>' +
+'      <SRS>EPSG:4346</SRS>' +
+'      <SRS>EPSG:4347</SRS>' +
+'      <SRS>EPSG:4348</SRS>' +
+'      <SRS>EPSG:4349</SRS>' +
+'      <SRS>EPSG:4350</SRS>' +
+'      <SRS>EPSG:4351</SRS>' +
+'      <SRS>EPSG:4352</SRS>' +
+'      <SRS>EPSG:4353</SRS>' +
+'      <SRS>EPSG:4354</SRS>' +
+'      <SRS>EPSG:4355</SRS>' +
+'      <SRS>EPSG:4356</SRS>' +
+'      <SRS>EPSG:4357</SRS>' +
+'      <SRS>EPSG:4358</SRS>' +
+'      <SRS>EPSG:4359</SRS>' +
+'      <SRS>EPSG:4360</SRS>' +
+'      <SRS>EPSG:4361</SRS>' +
+'      <SRS>EPSG:4362</SRS>' +
+'      <SRS>EPSG:4363</SRS>' +
+'      <SRS>EPSG:4364</SRS>' +
+'      <SRS>EPSG:4365</SRS>' +
+'      <SRS>EPSG:4366</SRS>' +
+'      <SRS>EPSG:4367</SRS>' +
+'      <SRS>EPSG:4368</SRS>' +
+'      <SRS>EPSG:4369</SRS>' +
+'      <SRS>EPSG:4370</SRS>' +
+'      <SRS>EPSG:4371</SRS>' +
+'      <SRS>EPSG:4372</SRS>' +
+'      <SRS>EPSG:4373</SRS>' +
+'      <SRS>EPSG:4374</SRS>' +
+'      <SRS>EPSG:4375</SRS>' +
+'      <SRS>EPSG:4376</SRS>' +
+'      <SRS>EPSG:4377</SRS>' +
+'      <SRS>EPSG:4378</SRS>' +
+'      <SRS>EPSG:4379</SRS>' +
+'      <SRS>EPSG:4380</SRS>' +
+'      <SRS>EPSG:4381</SRS>' +
+'      <SRS>EPSG:4382</SRS>' +
+'      <SRS>EPSG:4383</SRS>' +
+'      <SRS>EPSG:4384</SRS>' +
+'      <SRS>EPSG:4385</SRS>' +
+'      <SRS>EPSG:4386</SRS>' +
+'      <SRS>EPSG:4387</SRS>' +
+'      <SRS>EPSG:4388</SRS>' +
+'      <SRS>EPSG:4389</SRS>' +
+'      <SRS>EPSG:4600</SRS>' +
+'      <SRS>EPSG:4601</SRS>' +
+'      <SRS>EPSG:4602</SRS>' +
+'      <SRS>EPSG:4603</SRS>' +
+'      <SRS>EPSG:4604</SRS>' +
+'      <SRS>EPSG:4605</SRS>' +
+'      <SRS>EPSG:4606</SRS>' +
+'      <SRS>EPSG:4607</SRS>' +
+'      <SRS>EPSG:4608</SRS>' +
+'      <SRS>EPSG:4609</SRS>' +
+'      <SRS>EPSG:4610</SRS>' +
+'      <SRS>EPSG:4611</SRS>' +
+'      <SRS>EPSG:4612</SRS>' +
+'      <SRS>EPSG:4613</SRS>' +
+'      <SRS>EPSG:4614</SRS>' +
+'      <SRS>EPSG:4615</SRS>' +
+'      <SRS>EPSG:4616</SRS>' +
+'      <SRS>EPSG:4617</SRS>' +
+'      <SRS>EPSG:4618</SRS>' +
+'      <SRS>EPSG:4619</SRS>' +
+'      <SRS>EPSG:4620</SRS>' +
+'      <SRS>EPSG:4621</SRS>' +
+'      <SRS>EPSG:4622</SRS>' +
+'      <SRS>EPSG:4623</SRS>' +
+'      <SRS>EPSG:4624</SRS>' +
+'      <SRS>EPSG:4625</SRS>' +
+'      <SRS>EPSG:4626</SRS>' +
+'      <SRS>EPSG:4627</SRS>' +
+'      <SRS>EPSG:4628</SRS>' +
+'      <SRS>EPSG:4629</SRS>' +
+'      <SRS>EPSG:4630</SRS>' +
+'      <SRS>EPSG:4631</SRS>' +
+'      <SRS>EPSG:4632</SRS>' +
+'      <SRS>EPSG:4633</SRS>' +
+'      <SRS>EPSG:4634</SRS>' +
+'      <SRS>EPSG:4635</SRS>' +
+'      <SRS>EPSG:4636</SRS>' +
+'      <SRS>EPSG:4637</SRS>' +
+'      <SRS>EPSG:4638</SRS>' +
+'      <SRS>EPSG:4639</SRS>' +
+'      <SRS>EPSG:4640</SRS>' +
+'      <SRS>EPSG:4641</SRS>' +
+'      <SRS>EPSG:4642</SRS>' +
+'      <SRS>EPSG:4643</SRS>' +
+'      <SRS>EPSG:4644</SRS>' +
+'      <SRS>EPSG:4645</SRS>' +
+'      <SRS>EPSG:4646</SRS>' +
+'      <SRS>EPSG:4657</SRS>' +
+'      <SRS>EPSG:4658</SRS>' +
+'      <SRS>EPSG:4659</SRS>' +
+'      <SRS>EPSG:4660</SRS>' +
+'      <SRS>EPSG:4661</SRS>' +
+'      <SRS>EPSG:4662</SRS>' +
+'      <SRS>EPSG:4663</SRS>' +
+'      <SRS>EPSG:4664</SRS>' +
+'      <SRS>EPSG:4665</SRS>' +
+'      <SRS>EPSG:4666</SRS>' +
+'      <SRS>EPSG:4667</SRS>' +
+'      <SRS>EPSG:4668</SRS>' +
+'      <SRS>EPSG:4669</SRS>' +
+'      <SRS>EPSG:4670</SRS>' +
+'      <SRS>EPSG:4671</SRS>' +
+'      <SRS>EPSG:4672</SRS>' +
+'      <SRS>EPSG:4673</SRS>' +
+'      <SRS>EPSG:4674</SRS>' +
+'      <SRS>EPSG:4675</SRS>' +
+'      <SRS>EPSG:4676</SRS>' +
+'      <SRS>EPSG:4677</SRS>' +
+'      <SRS>EPSG:4678</SRS>' +
+'      <SRS>EPSG:4679</SRS>' +
+'      <SRS>EPSG:4680</SRS>' +
+'      <SRS>EPSG:4681</SRS>' +
+'      <SRS>EPSG:4682</SRS>' +
+'      <SRS>EPSG:4683</SRS>' +
+'      <SRS>EPSG:4684</SRS>' +
+'      <SRS>EPSG:4685</SRS>' +
+'      <SRS>EPSG:4686</SRS>' +
+'      <SRS>EPSG:4687</SRS>' +
+'      <SRS>EPSG:4688</SRS>' +
+'      <SRS>EPSG:4689</SRS>' +
+'      <SRS>EPSG:4690</SRS>' +
+'      <SRS>EPSG:4691</SRS>' +
+'      <SRS>EPSG:4692</SRS>' +
+'      <SRS>EPSG:4693</SRS>' +
+'      <SRS>EPSG:4694</SRS>' +
+'      <SRS>EPSG:4695</SRS>' +
+'      <SRS>EPSG:4696</SRS>' +
+'      <SRS>EPSG:4697</SRS>' +
+'      <SRS>EPSG:4698</SRS>' +
+'      <SRS>EPSG:4699</SRS>' +
+'      <SRS>EPSG:4700</SRS>' +
+'      <SRS>EPSG:4701</SRS>' +
+'      <SRS>EPSG:4702</SRS>' +
+'      <SRS>EPSG:4703</SRS>' +
+'      <SRS>EPSG:4704</SRS>' +
+'      <SRS>EPSG:4705</SRS>' +
+'      <SRS>EPSG:4706</SRS>' +
+'      <SRS>EPSG:4707</SRS>' +
+'      <SRS>EPSG:4708</SRS>' +
+'      <SRS>EPSG:4709</SRS>' +
+'      <SRS>EPSG:4710</SRS>' +
+'      <SRS>EPSG:4711</SRS>' +
+'      <SRS>EPSG:4712</SRS>' +
+'      <SRS>EPSG:4713</SRS>' +
+'      <SRS>EPSG:4714</SRS>' +
+'      <SRS>EPSG:4715</SRS>' +
+'      <SRS>EPSG:4716</SRS>' +
+'      <SRS>EPSG:4717</SRS>' +
+'      <SRS>EPSG:4718</SRS>' +
+'      <SRS>EPSG:4719</SRS>' +
+'      <SRS>EPSG:4720</SRS>' +
+'      <SRS>EPSG:4721</SRS>' +
+'      <SRS>EPSG:4722</SRS>' +
+'      <SRS>EPSG:4723</SRS>' +
+'      <SRS>EPSG:4724</SRS>' +
+'      <SRS>EPSG:4725</SRS>' +
+'      <SRS>EPSG:4726</SRS>' +
+'      <SRS>EPSG:4727</SRS>' +
+'      <SRS>EPSG:4728</SRS>' +
+'      <SRS>EPSG:4729</SRS>' +
+'      <SRS>EPSG:4730</SRS>' +
+'      <SRS>EPSG:4731</SRS>' +
+'      <SRS>EPSG:4732</SRS>' +
+'      <SRS>EPSG:4733</SRS>' +
+'      <SRS>EPSG:4734</SRS>' +
+'      <SRS>EPSG:4735</SRS>' +
+'      <SRS>EPSG:4736</SRS>' +
+'      <SRS>EPSG:4737</SRS>' +
+'      <SRS>EPSG:4738</SRS>' +
+'      <SRS>EPSG:4739</SRS>' +
+'      <SRS>EPSG:4740</SRS>' +
+'      <SRS>EPSG:4741</SRS>' +
+'      <SRS>EPSG:4742</SRS>' +
+'      <SRS>EPSG:4743</SRS>' +
+'      <SRS>EPSG:4744</SRS>' +
+'      <SRS>EPSG:4745</SRS>' +
+'      <SRS>EPSG:4746</SRS>' +
+'      <SRS>EPSG:4747</SRS>' +
+'      <SRS>EPSG:4748</SRS>' +
+'      <SRS>EPSG:4749</SRS>' +
+'      <SRS>EPSG:4750</SRS>' +
+'      <SRS>EPSG:4751</SRS>' +
+'      <SRS>EPSG:4752</SRS>' +
+'      <SRS>EPSG:4753</SRS>' +
+'      <SRS>EPSG:4754</SRS>' +
+'      <SRS>EPSG:4755</SRS>' +
+'      <SRS>EPSG:4756</SRS>' +
+'      <SRS>EPSG:4757</SRS>' +
+'      <SRS>EPSG:4758</SRS>' +
+'      <SRS>EPSG:4801</SRS>' +
+'      <SRS>EPSG:4802</SRS>' +
+'      <SRS>EPSG:4803</SRS>' +
+'      <SRS>EPSG:4804</SRS>' +
+'      <SRS>EPSG:4805</SRS>' +
+'      <SRS>EPSG:4806</SRS>' +
+'      <SRS>EPSG:4807</SRS>' +
+'      <SRS>EPSG:4808</SRS>' +
+'      <SRS>EPSG:4809</SRS>' +
+'      <SRS>EPSG:4810</SRS>' +
+'      <SRS>EPSG:4811</SRS>' +
+'      <SRS>EPSG:4813</SRS>' +
+'      <SRS>EPSG:4814</SRS>' +
+'      <SRS>EPSG:4815</SRS>' +
+'      <SRS>EPSG:4816</SRS>' +
+'      <SRS>EPSG:4817</SRS>' +
+'      <SRS>EPSG:4818</SRS>' +
+'      <SRS>EPSG:4819</SRS>' +
+'      <SRS>EPSG:4820</SRS>' +
+'      <SRS>EPSG:4821</SRS>' +
+'      <SRS>EPSG:4894</SRS>' +
+'      <SRS>EPSG:4895</SRS>' +
+'      <SRS>EPSG:4896</SRS>' +
+'      <SRS>EPSG:4897</SRS>' +
+'      <SRS>EPSG:4898</SRS>' +
+'      <SRS>EPSG:4899</SRS>' +
+'      <SRS>EPSG:4900</SRS>' +
+'      <SRS>EPSG:4901</SRS>' +
+'      <SRS>EPSG:4902</SRS>' +
+'      <SRS>EPSG:4903</SRS>' +
+'      <SRS>EPSG:4904</SRS>' +
+'      <SRS>EPSG:4906</SRS>' +
+'      <SRS>EPSG:4907</SRS>' +
+'      <SRS>EPSG:4908</SRS>' +
+'      <SRS>EPSG:4909</SRS>' +
+'      <SRS>EPSG:4910</SRS>' +
+'      <SRS>EPSG:4911</SRS>' +
+'      <SRS>EPSG:4912</SRS>' +
+'      <SRS>EPSG:4913</SRS>' +
+'      <SRS>EPSG:4914</SRS>' +
+'      <SRS>EPSG:4915</SRS>' +
+'      <SRS>EPSG:4916</SRS>' +
+'      <SRS>EPSG:4917</SRS>' +
+'      <SRS>EPSG:4918</SRS>' +
+'      <SRS>EPSG:4919</SRS>' +
+'      <SRS>EPSG:4920</SRS>' +
+'      <SRS>EPSG:4921</SRS>' +
+'      <SRS>EPSG:4922</SRS>' +
+'      <SRS>EPSG:4923</SRS>' +
+'      <SRS>EPSG:4924</SRS>' +
+'      <SRS>EPSG:4925</SRS>' +
+'      <SRS>EPSG:4926</SRS>' +
+'      <SRS>EPSG:4927</SRS>' +
+'      <SRS>EPSG:4928</SRS>' +
+'      <SRS>EPSG:4929</SRS>' +
+'      <SRS>EPSG:4930</SRS>' +
+'      <SRS>EPSG:4931</SRS>' +
+'      <SRS>EPSG:4932</SRS>' +
+'      <SRS>EPSG:4933</SRS>' +
+'      <SRS>EPSG:4934</SRS>' +
+'      <SRS>EPSG:4935</SRS>' +
+'      <SRS>EPSG:4936</SRS>' +
+'      <SRS>EPSG:4937</SRS>' +
+'      <SRS>EPSG:4938</SRS>' +
+'      <SRS>EPSG:4939</SRS>' +
+'      <SRS>EPSG:4940</SRS>' +
+'      <SRS>EPSG:4941</SRS>' +
+'      <SRS>EPSG:4942</SRS>' +
+'      <SRS>EPSG:4943</SRS>' +
+'      <SRS>EPSG:4944</SRS>' +
+'      <SRS>EPSG:4945</SRS>' +
+'      <SRS>EPSG:4946</SRS>' +
+'      <SRS>EPSG:4947</SRS>' +
+'      <SRS>EPSG:4948</SRS>' +
+'      <SRS>EPSG:4949</SRS>' +
+'      <SRS>EPSG:4950</SRS>' +
+'      <SRS>EPSG:4951</SRS>' +
+'      <SRS>EPSG:4952</SRS>' +
+'      <SRS>EPSG:4953</SRS>' +
+'      <SRS>EPSG:4954</SRS>' +
+'      <SRS>EPSG:4955</SRS>' +
+'      <SRS>EPSG:4956</SRS>' +
+'      <SRS>EPSG:4957</SRS>' +
+'      <SRS>EPSG:4958</SRS>' +
+'      <SRS>EPSG:4959</SRS>' +
+'      <SRS>EPSG:4960</SRS>' +
+'      <SRS>EPSG:4961</SRS>' +
+'      <SRS>EPSG:4962</SRS>' +
+'      <SRS>EPSG:4963</SRS>' +
+'      <SRS>EPSG:4964</SRS>' +
+'      <SRS>EPSG:4965</SRS>' +
+'      <SRS>EPSG:4966</SRS>' +
+'      <SRS>EPSG:4967</SRS>' +
+'      <SRS>EPSG:4968</SRS>' +
+'      <SRS>EPSG:4969</SRS>' +
+'      <SRS>EPSG:4970</SRS>' +
+'      <SRS>EPSG:4971</SRS>' +
+'      <SRS>EPSG:4972</SRS>' +
+'      <SRS>EPSG:4973</SRS>' +
+'      <SRS>EPSG:4974</SRS>' +
+'      <SRS>EPSG:4975</SRS>' +
+'      <SRS>EPSG:4976</SRS>' +
+'      <SRS>EPSG:4977</SRS>' +
+'      <SRS>EPSG:4978</SRS>' +
+'      <SRS>EPSG:4979</SRS>' +
+'      <SRS>EPSG:4980</SRS>' +
+'      <SRS>EPSG:4981</SRS>' +
+'      <SRS>EPSG:4982</SRS>' +
+'      <SRS>EPSG:4983</SRS>' +
+'      <SRS>EPSG:4984</SRS>' +
+'      <SRS>EPSG:4985</SRS>' +
+'      <SRS>EPSG:4986</SRS>' +
+'      <SRS>EPSG:4987</SRS>' +
+'      <SRS>EPSG:4988</SRS>' +
+'      <SRS>EPSG:4989</SRS>' +
+'      <SRS>EPSG:4990</SRS>' +
+'      <SRS>EPSG:4991</SRS>' +
+'      <SRS>EPSG:4992</SRS>' +
+'      <SRS>EPSG:4993</SRS>' +
+'      <SRS>EPSG:4994</SRS>' +
+'      <SRS>EPSG:4995</SRS>' +
+'      <SRS>EPSG:4996</SRS>' +
+'      <SRS>EPSG:4997</SRS>' +
+'      <SRS>EPSG:4998</SRS>' +
+'      <SRS>EPSG:4999</SRS>' +
+'      <SRS>EPSG:5600</SRS>' +
+'      <SRS>EPSG:5601</SRS>' +
+'      <SRS>EPSG:5602</SRS>' +
+'      <SRS>EPSG:5603</SRS>' +
+'      <SRS>EPSG:5604</SRS>' +
+'      <SRS>EPSG:5605</SRS>' +
+'      <SRS>EPSG:5606</SRS>' +
+'      <SRS>EPSG:5607</SRS>' +
+'      <SRS>EPSG:5608</SRS>' +
+'      <SRS>EPSG:5609</SRS>' +
+'      <SRS>EPSG:5701</SRS>' +
+'      <SRS>EPSG:5702</SRS>' +
+'      <SRS>EPSG:5703</SRS>' +
+'      <SRS>EPSG:5704</SRS>' +
+'      <SRS>EPSG:5705</SRS>' +
+'      <SRS>EPSG:5706</SRS>' +
+'      <SRS>EPSG:5709</SRS>' +
+'      <SRS>EPSG:5710</SRS>' +
+'      <SRS>EPSG:5711</SRS>' +
+'      <SRS>EPSG:5712</SRS>' +
+'      <SRS>EPSG:5713</SRS>' +
+'      <SRS>EPSG:5714</SRS>' +
+'      <SRS>EPSG:5715</SRS>' +
+'      <SRS>EPSG:5716</SRS>' +
+'      <SRS>EPSG:5717</SRS>' +
+'      <SRS>EPSG:5718</SRS>' +
+'      <SRS>EPSG:5719</SRS>' +
+'      <SRS>EPSG:5720</SRS>' +
+'      <SRS>EPSG:5721</SRS>' +
+'      <SRS>EPSG:5722</SRS>' +
+'      <SRS>EPSG:5723</SRS>' +
+'      <SRS>EPSG:5724</SRS>' +
+'      <SRS>EPSG:5725</SRS>' +
+'      <SRS>EPSG:5726</SRS>' +
+'      <SRS>EPSG:5727</SRS>' +
+'      <SRS>EPSG:5728</SRS>' +
+'      <SRS>EPSG:5729</SRS>' +
+'      <SRS>EPSG:5730</SRS>' +
+'      <SRS>EPSG:5731</SRS>' +
+'      <SRS>EPSG:5732</SRS>' +
+'      <SRS>EPSG:5733</SRS>' +
+'      <SRS>EPSG:5734</SRS>' +
+'      <SRS>EPSG:5735</SRS>' +
+'      <SRS>EPSG:5736</SRS>' +
+'      <SRS>EPSG:5737</SRS>' +
+'      <SRS>EPSG:5738</SRS>' +
+'      <SRS>EPSG:5739</SRS>' +
+'      <SRS>EPSG:5740</SRS>' +
+'      <SRS>EPSG:5741</SRS>' +
+'      <SRS>EPSG:5742</SRS>' +
+'      <SRS>EPSG:5743</SRS>' +
+'      <SRS>EPSG:5744</SRS>' +
+'      <SRS>EPSG:5745</SRS>' +
+'      <SRS>EPSG:5746</SRS>' +
+'      <SRS>EPSG:5747</SRS>' +
+'      <SRS>EPSG:5748</SRS>' +
+'      <SRS>EPSG:5749</SRS>' +
+'      <SRS>EPSG:5750</SRS>' +
+'      <SRS>EPSG:5751</SRS>' +
+'      <SRS>EPSG:5752</SRS>' +
+'      <SRS>EPSG:5753</SRS>' +
+'      <SRS>EPSG:5754</SRS>' +
+'      <SRS>EPSG:5755</SRS>' +
+'      <SRS>EPSG:5756</SRS>' +
+'      <SRS>EPSG:5757</SRS>' +
+'      <SRS>EPSG:5758</SRS>' +
+'      <SRS>EPSG:5759</SRS>' +
+'      <SRS>EPSG:5760</SRS>' +
+'      <SRS>EPSG:5761</SRS>' +
+'      <SRS>EPSG:5762</SRS>' +
+'      <SRS>EPSG:5763</SRS>' +
+'      <SRS>EPSG:5764</SRS>' +
+'      <SRS>EPSG:5765</SRS>' +
+'      <SRS>EPSG:5766</SRS>' +
+'      <SRS>EPSG:5767</SRS>' +
+'      <SRS>EPSG:5768</SRS>' +
+'      <SRS>EPSG:5769</SRS>' +
+'      <SRS>EPSG:5770</SRS>' +
+'      <SRS>EPSG:5771</SRS>' +
+'      <SRS>EPSG:5772</SRS>' +
+'      <SRS>EPSG:5773</SRS>' +
+'      <SRS>EPSG:5774</SRS>' +
+'      <SRS>EPSG:5775</SRS>' +
+'      <SRS>EPSG:5776</SRS>' +
+'      <SRS>EPSG:5777</SRS>' +
+'      <SRS>EPSG:5778</SRS>' +
+'      <SRS>EPSG:5779</SRS>' +
+'      <SRS>EPSG:5780</SRS>' +
+'      <SRS>EPSG:5781</SRS>' +
+'      <SRS>EPSG:5782</SRS>' +
+'      <SRS>EPSG:5783</SRS>' +
+'      <SRS>EPSG:5784</SRS>' +
+'      <SRS>EPSG:5785</SRS>' +
+'      <SRS>EPSG:5786</SRS>' +
+'      <SRS>EPSG:5787</SRS>' +
+'      <SRS>EPSG:5788</SRS>' +
+'      <SRS>EPSG:5789</SRS>' +
+'      <SRS>EPSG:5790</SRS>' +
+'      <SRS>EPSG:5791</SRS>' +
+'      <SRS>EPSG:5792</SRS>' +
+'      <SRS>EPSG:5793</SRS>' +
+'      <SRS>EPSG:5794</SRS>' +
+'      <SRS>EPSG:5795</SRS>' +
+'      <SRS>EPSG:5796</SRS>' +
+'      <SRS>EPSG:5797</SRS>' +
+'      <SRS>EPSG:5798</SRS>' +
+'      <SRS>EPSG:5799</SRS>' +
+'      <SRS>EPSG:5800</SRS>' +
+'      <SRS>EPSG:5801</SRS>' +
+'      <SRS>EPSG:5802</SRS>' +
+'      <SRS>EPSG:5803</SRS>' +
+'      <SRS>EPSG:5804</SRS>' +
+'      <SRS>EPSG:5805</SRS>' +
+'      <SRS>EPSG:5806</SRS>' +
+'      <SRS>EPSG:5807</SRS>' +
+'      <SRS>EPSG:5808</SRS>' +
+'      <SRS>EPSG:5809</SRS>' +
+'      <SRS>EPSG:5810</SRS>' +
+'      <SRS>EPSG:5811</SRS>' +
+'      <SRS>EPSG:5812</SRS>' +
+'      <SRS>EPSG:5813</SRS>' +
+'      <SRS>EPSG:5814</SRS>' +
+'      <SRS>EPSG:5815</SRS>' +
+'      <SRS>EPSG:5816</SRS>' +
+'      <SRS>EPSG:5817</SRS>' +
+'      <SRS>EPSG:5818</SRS>' +
+'      <SRS>EPSG:7400</SRS>' +
+'      <SRS>EPSG:7401</SRS>' +
+'      <SRS>EPSG:7402</SRS>' +
+'      <SRS>EPSG:7403</SRS>' +
+'      <SRS>EPSG:7404</SRS>' +
+'      <SRS>EPSG:7405</SRS>' +
+'      <SRS>EPSG:7406</SRS>' +
+'      <SRS>EPSG:7407</SRS>' +
+'      <SRS>EPSG:7408</SRS>' +
+'      <SRS>EPSG:7409</SRS>' +
+'      <SRS>EPSG:7410</SRS>' +
+'      <SRS>EPSG:7411</SRS>' +
+'      <SRS>EPSG:7412</SRS>' +
+'      <SRS>EPSG:7413</SRS>' +
+'      <SRS>EPSG:7414</SRS>' +
+'      <SRS>EPSG:7415</SRS>' +
+'      <SRS>EPSG:7416</SRS>' +
+'      <SRS>EPSG:7417</SRS>' +
+'      <SRS>EPSG:7418</SRS>' +
+'      <SRS>EPSG:7419</SRS>' +
+'      <SRS>EPSG:7420</SRS>' +
+'      <SRS>EPSG:20004</SRS>' +
+'      <SRS>EPSG:20005</SRS>' +
+'      <SRS>EPSG:20006</SRS>' +
+'      <SRS>EPSG:20007</SRS>' +
+'      <SRS>EPSG:20008</SRS>' +
+'      <SRS>EPSG:20009</SRS>' +
+'      <SRS>EPSG:20010</SRS>' +
+'      <SRS>EPSG:20011</SRS>' +
+'      <SRS>EPSG:20012</SRS>' +
+'      <SRS>EPSG:20013</SRS>' +
+'      <SRS>EPSG:20014</SRS>' +
+'      <SRS>EPSG:20015</SRS>' +
+'      <SRS>EPSG:20016</SRS>' +
+'      <SRS>EPSG:20017</SRS>' +
+'      <SRS>EPSG:20018</SRS>' +
+'      <SRS>EPSG:20019</SRS>' +
+'      <SRS>EPSG:20020</SRS>' +
+'      <SRS>EPSG:20021</SRS>' +
+'      <SRS>EPSG:20022</SRS>' +
+'      <SRS>EPSG:20023</SRS>' +
+'      <SRS>EPSG:20024</SRS>' +
+'      <SRS>EPSG:20025</SRS>' +
+'      <SRS>EPSG:20026</SRS>' +
+'      <SRS>EPSG:20027</SRS>' +
+'      <SRS>EPSG:20028</SRS>' +
+'      <SRS>EPSG:20029</SRS>' +
+'      <SRS>EPSG:20030</SRS>' +
+'      <SRS>EPSG:20031</SRS>' +
+'      <SRS>EPSG:20032</SRS>' +
+'      <SRS>EPSG:20064</SRS>' +
+'      <SRS>EPSG:20065</SRS>' +
+'      <SRS>EPSG:20066</SRS>' +
+'      <SRS>EPSG:20067</SRS>' +
+'      <SRS>EPSG:20068</SRS>' +
+'      <SRS>EPSG:20069</SRS>' +
+'      <SRS>EPSG:20070</SRS>' +
+'      <SRS>EPSG:20071</SRS>' +
+'      <SRS>EPSG:20072</SRS>' +
+'      <SRS>EPSG:20073</SRS>' +
+'      <SRS>EPSG:20074</SRS>' +
+'      <SRS>EPSG:20075</SRS>' +
+'      <SRS>EPSG:20076</SRS>' +
+'      <SRS>EPSG:20077</SRS>' +
+'      <SRS>EPSG:20078</SRS>' +
+'      <SRS>EPSG:20079</SRS>' +
+'      <SRS>EPSG:20080</SRS>' +
+'      <SRS>EPSG:20081</SRS>' +
+'      <SRS>EPSG:20082</SRS>' +
+'      <SRS>EPSG:20083</SRS>' +
+'      <SRS>EPSG:20084</SRS>' +
+'      <SRS>EPSG:20085</SRS>' +
+'      <SRS>EPSG:20086</SRS>' +
+'      <SRS>EPSG:20087</SRS>' +
+'      <SRS>EPSG:20088</SRS>' +
+'      <SRS>EPSG:20089</SRS>' +
+'      <SRS>EPSG:20090</SRS>' +
+'      <SRS>EPSG:20091</SRS>' +
+'      <SRS>EPSG:20092</SRS>' +
+'      <SRS>EPSG:20135</SRS>' +
+'      <SRS>EPSG:20136</SRS>' +
+'      <SRS>EPSG:20137</SRS>' +
+'      <SRS>EPSG:20138</SRS>' +
+'      <SRS>EPSG:20248</SRS>' +
+'      <SRS>EPSG:20249</SRS>' +
+'      <SRS>EPSG:20250</SRS>' +
+'      <SRS>EPSG:20251</SRS>' +
+'      <SRS>EPSG:20252</SRS>' +
+'      <SRS>EPSG:20253</SRS>' +
+'      <SRS>EPSG:20254</SRS>' +
+'      <SRS>EPSG:20255</SRS>' +
+'      <SRS>EPSG:20256</SRS>' +
+'      <SRS>EPSG:20257</SRS>' +
+'      <SRS>EPSG:20258</SRS>' +
+'      <SRS>EPSG:20348</SRS>' +
+'      <SRS>EPSG:20349</SRS>' +
+'      <SRS>EPSG:20350</SRS>' +
+'      <SRS>EPSG:20351</SRS>' +
+'      <SRS>EPSG:20352</SRS>' +
+'      <SRS>EPSG:20353</SRS>' +
+'      <SRS>EPSG:20354</SRS>' +
+'      <SRS>EPSG:20355</SRS>' +
+'      <SRS>EPSG:20356</SRS>' +
+'      <SRS>EPSG:20357</SRS>' +
+'      <SRS>EPSG:20358</SRS>' +
+'      <SRS>EPSG:20436</SRS>' +
+'      <SRS>EPSG:20437</SRS>' +
+'      <SRS>EPSG:20438</SRS>' +
+'      <SRS>EPSG:20439</SRS>' +
+'      <SRS>EPSG:20440</SRS>' +
+'      <SRS>EPSG:20499</SRS>' +
+'      <SRS>EPSG:20538</SRS>' +
+'      <SRS>EPSG:20539</SRS>' +
+'      <SRS>EPSG:20790</SRS>' +
+'      <SRS>EPSG:20791</SRS>' +
+'      <SRS>EPSG:20822</SRS>' +
+'      <SRS>EPSG:20823</SRS>' +
+'      <SRS>EPSG:20824</SRS>' +
+'      <SRS>EPSG:20934</SRS>' +
+'      <SRS>EPSG:20935</SRS>' +
+'      <SRS>EPSG:20936</SRS>' +
+'      <SRS>EPSG:21035</SRS>' +
+'      <SRS>EPSG:21036</SRS>' +
+'      <SRS>EPSG:21037</SRS>' +
+'      <SRS>EPSG:21095</SRS>' +
+'      <SRS>EPSG:21096</SRS>' +
+'      <SRS>EPSG:21097</SRS>' +
+'      <SRS>EPSG:21100</SRS>' +
+'      <SRS>EPSG:21148</SRS>' +
+'      <SRS>EPSG:21149</SRS>' +
+'      <SRS>EPSG:21150</SRS>' +
+'      <SRS>EPSG:21291</SRS>' +
+'      <SRS>EPSG:21292</SRS>' +
+'      <SRS>EPSG:21413</SRS>' +
+'      <SRS>EPSG:21414</SRS>' +
+'      <SRS>EPSG:21415</SRS>' +
+'      <SRS>EPSG:21416</SRS>' +
+'      <SRS>EPSG:21417</SRS>' +
+'      <SRS>EPSG:21418</SRS>' +
+'      <SRS>EPSG:21419</SRS>' +
+'      <SRS>EPSG:21420</SRS>' +
+'      <SRS>EPSG:21421</SRS>' +
+'      <SRS>EPSG:21422</SRS>' +
+'      <SRS>EPSG:21423</SRS>' +
+'      <SRS>EPSG:21453</SRS>' +
+'      <SRS>EPSG:21454</SRS>' +
+'      <SRS>EPSG:21455</SRS>' +
+'      <SRS>EPSG:21456</SRS>' +
+'      <SRS>EPSG:21457</SRS>' +
+'      <SRS>EPSG:21458</SRS>' +
+'      <SRS>EPSG:21459</SRS>' +
+'      <SRS>EPSG:21460</SRS>' +
+'      <SRS>EPSG:21461</SRS>' +
+'      <SRS>EPSG:21462</SRS>' +
+'      <SRS>EPSG:21463</SRS>' +
+'      <SRS>EPSG:21473</SRS>' +
+'      <SRS>EPSG:21474</SRS>' +
+'      <SRS>EPSG:21475</SRS>' +
+'      <SRS>EPSG:21476</SRS>' +
+'      <SRS>EPSG:21477</SRS>' +
+'      <SRS>EPSG:21478</SRS>' +
+'      <SRS>EPSG:21479</SRS>' +
+'      <SRS>EPSG:21480</SRS>' +
+'      <SRS>EPSG:21481</SRS>' +
+'      <SRS>EPSG:21482</SRS>' +
+'      <SRS>EPSG:21483</SRS>' +
+'      <SRS>EPSG:21500</SRS>' +
+'      <SRS>EPSG:21780</SRS>' +
+'      <SRS>EPSG:21781</SRS>' +
+'      <SRS>EPSG:21817</SRS>' +
+'      <SRS>EPSG:21818</SRS>' +
+'      <SRS>EPSG:21891</SRS>' +
+'      <SRS>EPSG:21892</SRS>' +
+'      <SRS>EPSG:21893</SRS>' +
+'      <SRS>EPSG:21894</SRS>' +
+'      <SRS>EPSG:21896</SRS>' +
+'      <SRS>EPSG:21897</SRS>' +
+'      <SRS>EPSG:21898</SRS>' +
+'      <SRS>EPSG:21899</SRS>' +
+'      <SRS>EPSG:22032</SRS>' +
+'      <SRS>EPSG:22033</SRS>' +
+'      <SRS>EPSG:22091</SRS>' +
+'      <SRS>EPSG:22092</SRS>' +
+'      <SRS>EPSG:22171</SRS>' +
+'      <SRS>EPSG:22172</SRS>' +
+'      <SRS>EPSG:22173</SRS>' +
+'      <SRS>EPSG:22174</SRS>' +
+'      <SRS>EPSG:22175</SRS>' +
+'      <SRS>EPSG:22176</SRS>' +
+'      <SRS>EPSG:22177</SRS>' +
+'      <SRS>EPSG:22181</SRS>' +
+'      <SRS>EPSG:22182</SRS>' +
+'      <SRS>EPSG:22183</SRS>' +
+'      <SRS>EPSG:22184</SRS>' +
+'      <SRS>EPSG:22185</SRS>' +
+'      <SRS>EPSG:22186</SRS>' +
+'      <SRS>EPSG:22187</SRS>' +
+'      <SRS>EPSG:22191</SRS>' +
+'      <SRS>EPSG:22192</SRS>' +
+'      <SRS>EPSG:22193</SRS>' +
+'      <SRS>EPSG:22194</SRS>' +
+'      <SRS>EPSG:22195</SRS>' +
+'      <SRS>EPSG:22196</SRS>' +
+'      <SRS>EPSG:22197</SRS>' +
+'      <SRS>EPSG:22234</SRS>' +
+'      <SRS>EPSG:22235</SRS>' +
+'      <SRS>EPSG:22236</SRS>' +
+'      <SRS>EPSG:22275</SRS>' +
+'      <SRS>EPSG:22277</SRS>' +
+'      <SRS>EPSG:22279</SRS>' +
+'      <SRS>EPSG:22281</SRS>' +
+'      <SRS>EPSG:22283</SRS>' +
+'      <SRS>EPSG:22285</SRS>' +
+'      <SRS>EPSG:22287</SRS>' +
+'      <SRS>EPSG:22289</SRS>' +
+'      <SRS>EPSG:22291</SRS>' +
+'      <SRS>EPSG:22293</SRS>' +
+'      <SRS>EPSG:22300</SRS>' +
+'      <SRS>EPSG:22332</SRS>' +
+'      <SRS>EPSG:22391</SRS>' +
+'      <SRS>EPSG:22392</SRS>' +
+'      <SRS>EPSG:22521</SRS>' +
+'      <SRS>EPSG:22522</SRS>' +
+'      <SRS>EPSG:22523</SRS>' +
+'      <SRS>EPSG:22524</SRS>' +
+'      <SRS>EPSG:22525</SRS>' +
+'      <SRS>EPSG:22700</SRS>' +
+'      <SRS>EPSG:22770</SRS>' +
+'      <SRS>EPSG:22780</SRS>' +
+'      <SRS>EPSG:22832</SRS>' +
+'      <SRS>EPSG:22991</SRS>' +
+'      <SRS>EPSG:22992</SRS>' +
+'      <SRS>EPSG:22993</SRS>' +
+'      <SRS>EPSG:22994</SRS>' +
+'      <SRS>EPSG:23028</SRS>' +
+'      <SRS>EPSG:23029</SRS>' +
+'      <SRS>EPSG:23030</SRS>' +
+'      <SRS>EPSG:23031</SRS>' +
+'      <SRS>EPSG:23032</SRS>' +
+'      <SRS>EPSG:23033</SRS>' +
+'      <SRS>EPSG:23034</SRS>' +
+'      <SRS>EPSG:23035</SRS>' +
+'      <SRS>EPSG:23036</SRS>' +
+'      <SRS>EPSG:23037</SRS>' +
+'      <SRS>EPSG:23038</SRS>' +
+'      <SRS>EPSG:23090</SRS>' +
+'      <SRS>EPSG:23095</SRS>' +
+'      <SRS>EPSG:23239</SRS>' +
+'      <SRS>EPSG:23240</SRS>' +
+'      <SRS>EPSG:23433</SRS>' +
+'      <SRS>EPSG:23700</SRS>' +
+'      <SRS>EPSG:23846</SRS>' +
+'      <SRS>EPSG:23847</SRS>' +
+'      <SRS>EPSG:23848</SRS>' +
+'      <SRS>EPSG:23849</SRS>' +
+'      <SRS>EPSG:23850</SRS>' +
+'      <SRS>EPSG:23851</SRS>' +
+'      <SRS>EPSG:23852</SRS>' +
+'      <SRS>EPSG:23853</SRS>' +
+'      <SRS>EPSG:23866</SRS>' +
+'      <SRS>EPSG:23867</SRS>' +
+'      <SRS>EPSG:23868</SRS>' +
+'      <SRS>EPSG:23869</SRS>' +
+'      <SRS>EPSG:23870</SRS>' +
+'      <SRS>EPSG:23871</SRS>' +
+'      <SRS>EPSG:23872</SRS>' +
+'      <SRS>EPSG:23877</SRS>' +
+'      <SRS>EPSG:23878</SRS>' +
+'      <SRS>EPSG:23879</SRS>' +
+'      <SRS>EPSG:23880</SRS>' +
+'      <SRS>EPSG:23881</SRS>' +
+'      <SRS>EPSG:23882</SRS>' +
+'      <SRS>EPSG:23883</SRS>' +
+'      <SRS>EPSG:23884</SRS>' +
+'      <SRS>EPSG:23886</SRS>' +
+'      <SRS>EPSG:23887</SRS>' +
+'      <SRS>EPSG:23888</SRS>' +
+'      <SRS>EPSG:23889</SRS>' +
+'      <SRS>EPSG:23890</SRS>' +
+'      <SRS>EPSG:23891</SRS>' +
+'      <SRS>EPSG:23892</SRS>' +
+'      <SRS>EPSG:23893</SRS>' +
+'      <SRS>EPSG:23894</SRS>' +
+'      <SRS>EPSG:23946</SRS>' +
+'      <SRS>EPSG:23947</SRS>' +
+'      <SRS>EPSG:23948</SRS>' +
+'      <SRS>EPSG:24047</SRS>' +
+'      <SRS>EPSG:24048</SRS>' +
+'      <SRS>EPSG:24100</SRS>' +
+'      <SRS>EPSG:24200</SRS>' +
+'      <SRS>EPSG:24305</SRS>' +
+'      <SRS>EPSG:24306</SRS>' +
+'      <SRS>EPSG:24311</SRS>' +
+'      <SRS>EPSG:24312</SRS>' +
+'      <SRS>EPSG:24313</SRS>' +
+'      <SRS>EPSG:24342</SRS>' +
+'      <SRS>EPSG:24343</SRS>' +
+'      <SRS>EPSG:24344</SRS>' +
+'      <SRS>EPSG:24345</SRS>' +
+'      <SRS>EPSG:24346</SRS>' +
+'      <SRS>EPSG:24347</SRS>' +
+'      <SRS>EPSG:24370</SRS>' +
+'      <SRS>EPSG:24371</SRS>' +
+'      <SRS>EPSG:24372</SRS>' +
+'      <SRS>EPSG:24373</SRS>' +
+'      <SRS>EPSG:24374</SRS>' +
+'      <SRS>EPSG:24375</SRS>' +
+'      <SRS>EPSG:24376</SRS>' +
+'      <SRS>EPSG:24377</SRS>' +
+'      <SRS>EPSG:24378</SRS>' +
+'      <SRS>EPSG:24379</SRS>' +
+'      <SRS>EPSG:24380</SRS>' +
+'      <SRS>EPSG:24381</SRS>' +
+'      <SRS>EPSG:24382</SRS>' +
+'      <SRS>EPSG:24383</SRS>' +
+'      <SRS>EPSG:24500</SRS>' +
+'      <SRS>EPSG:24547</SRS>' +
+'      <SRS>EPSG:24548</SRS>' +
+'      <SRS>EPSG:24571</SRS>' +
+'      <SRS>EPSG:24600</SRS>' +
+'      <SRS>EPSG:24718</SRS>' +
+'      <SRS>EPSG:24719</SRS>' +
+'      <SRS>EPSG:24720</SRS>' +
+'      <SRS>EPSG:24817</SRS>' +
+'      <SRS>EPSG:24818</SRS>' +
+'      <SRS>EPSG:24819</SRS>' +
+'      <SRS>EPSG:24820</SRS>' +
+'      <SRS>EPSG:24821</SRS>' +
+'      <SRS>EPSG:24877</SRS>' +
+'      <SRS>EPSG:24878</SRS>' +
+'      <SRS>EPSG:24879</SRS>' +
+'      <SRS>EPSG:24880</SRS>' +
+'      <SRS>EPSG:24881</SRS>' +
+'      <SRS>EPSG:24882</SRS>' +
+'      <SRS>EPSG:24891</SRS>' +
+'      <SRS>EPSG:24892</SRS>' +
+'      <SRS>EPSG:24893</SRS>' +
+'      <SRS>EPSG:25000</SRS>' +
+'      <SRS>EPSG:25231</SRS>' +
+'      <SRS>EPSG:25391</SRS>' +
+'      <SRS>EPSG:25392</SRS>' +
+'      <SRS>EPSG:25393</SRS>' +
+'      <SRS>EPSG:25394</SRS>' +
+'      <SRS>EPSG:25395</SRS>' +
+'      <SRS>EPSG:25700</SRS>' +
+'      <SRS>EPSG:25828</SRS>' +
+'      <SRS>EPSG:25829</SRS>' +
+'      <SRS>EPSG:25830</SRS>' +
+'      <SRS>EPSG:25831</SRS>' +
+'      <SRS>EPSG:25832</SRS>' +
+'      <SRS>EPSG:25833</SRS>' +
+'      <SRS>EPSG:25834</SRS>' +
+'      <SRS>EPSG:25835</SRS>' +
+'      <SRS>EPSG:25836</SRS>' +
+'      <SRS>EPSG:25837</SRS>' +
+'      <SRS>EPSG:25838</SRS>' +
+'      <SRS>EPSG:25884</SRS>' +
+'      <SRS>EPSG:25932</SRS>' +
+'      <SRS>EPSG:26191</SRS>' +
+'      <SRS>EPSG:26192</SRS>' +
+'      <SRS>EPSG:26193</SRS>' +
+'      <SRS>EPSG:26194</SRS>' +
+'      <SRS>EPSG:26195</SRS>' +
+'      <SRS>EPSG:26237</SRS>' +
+'      <SRS>EPSG:26331</SRS>' +
+'      <SRS>EPSG:26332</SRS>' +
+'      <SRS>EPSG:26391</SRS>' +
+'      <SRS>EPSG:26392</SRS>' +
+'      <SRS>EPSG:26393</SRS>' +
+'      <SRS>EPSG:26432</SRS>' +
+'      <SRS>EPSG:26591</SRS>' +
+'      <SRS>EPSG:26592</SRS>' +
+'      <SRS>EPSG:26632</SRS>' +
+'      <SRS>EPSG:26692</SRS>' +
+'      <SRS>EPSG:26701</SRS>' +
+'      <SRS>EPSG:26702</SRS>' +
+'      <SRS>EPSG:26703</SRS>' +
+'      <SRS>EPSG:26704</SRS>' +
+'      <SRS>EPSG:26705</SRS>' +
+'      <SRS>EPSG:26706</SRS>' +
+'      <SRS>EPSG:26707</SRS>' +
+'      <SRS>EPSG:26708</SRS>' +
+'      <SRS>EPSG:26709</SRS>' +
+'      <SRS>EPSG:26710</SRS>' +
+'      <SRS>EPSG:26711</SRS>' +
+'      <SRS>EPSG:26712</SRS>' +
+'      <SRS>EPSG:26713</SRS>' +
+'      <SRS>EPSG:26714</SRS>' +
+'      <SRS>EPSG:26715</SRS>' +
+'      <SRS>EPSG:26716</SRS>' +
+'      <SRS>EPSG:26717</SRS>' +
+'      <SRS>EPSG:26718</SRS>' +
+'      <SRS>EPSG:26719</SRS>' +
+'      <SRS>EPSG:26720</SRS>' +
+'      <SRS>EPSG:26721</SRS>' +
+'      <SRS>EPSG:26722</SRS>' +
+'      <SRS>EPSG:26729</SRS>' +
+'      <SRS>EPSG:26730</SRS>' +
+'      <SRS>EPSG:26731</SRS>' +
+'      <SRS>EPSG:26732</SRS>' +
+'      <SRS>EPSG:26733</SRS>' +
+'      <SRS>EPSG:26734</SRS>' +
+'      <SRS>EPSG:26735</SRS>' +
+'      <SRS>EPSG:26736</SRS>' +
+'      <SRS>EPSG:26737</SRS>' +
+'      <SRS>EPSG:26738</SRS>' +
+'      <SRS>EPSG:26739</SRS>' +
+'      <SRS>EPSG:26740</SRS>' +
+'      <SRS>EPSG:26741</SRS>' +
+'      <SRS>EPSG:26742</SRS>' +
+'      <SRS>EPSG:26743</SRS>' +
+'      <SRS>EPSG:26744</SRS>' +
+'      <SRS>EPSG:26745</SRS>' +
+'      <SRS>EPSG:26746</SRS>' +
+'      <SRS>EPSG:26747</SRS>' +
+'      <SRS>EPSG:26748</SRS>' +
+'      <SRS>EPSG:26749</SRS>' +
+'      <SRS>EPSG:26750</SRS>' +
+'      <SRS>EPSG:26751</SRS>' +
+'      <SRS>EPSG:26752</SRS>' +
+'      <SRS>EPSG:26753</SRS>' +
+'      <SRS>EPSG:26754</SRS>' +
+'      <SRS>EPSG:26755</SRS>' +
+'      <SRS>EPSG:26756</SRS>' +
+'      <SRS>EPSG:26757</SRS>' +
+'      <SRS>EPSG:26758</SRS>' +
+'      <SRS>EPSG:26759</SRS>' +
+'      <SRS>EPSG:26760</SRS>' +
+'      <SRS>EPSG:26766</SRS>' +
+'      <SRS>EPSG:26767</SRS>' +
+'      <SRS>EPSG:26768</SRS>' +
+'      <SRS>EPSG:26769</SRS>' +
+'      <SRS>EPSG:26770</SRS>' +
+'      <SRS>EPSG:26771</SRS>' +
+'      <SRS>EPSG:26772</SRS>' +
+'      <SRS>EPSG:26773</SRS>' +
+'      <SRS>EPSG:26774</SRS>' +
+'      <SRS>EPSG:26775</SRS>' +
+'      <SRS>EPSG:26776</SRS>' +
+'      <SRS>EPSG:26777</SRS>' +
+'      <SRS>EPSG:26778</SRS>' +
+'      <SRS>EPSG:26779</SRS>' +
+'      <SRS>EPSG:26780</SRS>' +
+'      <SRS>EPSG:26781</SRS>' +
+'      <SRS>EPSG:26782</SRS>' +
+'      <SRS>EPSG:26783</SRS>' +
+'      <SRS>EPSG:26784</SRS>' +
+'      <SRS>EPSG:26785</SRS>' +
+'      <SRS>EPSG:26786</SRS>' +
+'      <SRS>EPSG:26787</SRS>' +
+'      <SRS>EPSG:26791</SRS>' +
+'      <SRS>EPSG:26792</SRS>' +
+'      <SRS>EPSG:26793</SRS>' +
+'      <SRS>EPSG:26794</SRS>' +
+'      <SRS>EPSG:26795</SRS>' +
+'      <SRS>EPSG:26796</SRS>' +
+'      <SRS>EPSG:26797</SRS>' +
+'      <SRS>EPSG:26798</SRS>' +
+'      <SRS>EPSG:26799</SRS>' +
+'      <SRS>EPSG:26801</SRS>' +
+'      <SRS>EPSG:26802</SRS>' +
+'      <SRS>EPSG:26803</SRS>' +
+'      <SRS>EPSG:26811</SRS>' +
+'      <SRS>EPSG:26812</SRS>' +
+'      <SRS>EPSG:26813</SRS>' +
+'      <SRS>EPSG:26901</SRS>' +
+'      <SRS>EPSG:26902</SRS>' +
+'      <SRS>EPSG:26903</SRS>' +
+'      <SRS>EPSG:26904</SRS>' +
+'      <SRS>EPSG:26905</SRS>' +
+'      <SRS>EPSG:26906</SRS>' +
+'      <SRS>EPSG:26907</SRS>' +
+'      <SRS>EPSG:26908</SRS>' +
+'      <SRS>EPSG:26909</SRS>' +
+'      <SRS>EPSG:26910</SRS>' +
+'      <SRS>EPSG:26911</SRS>' +
+'      <SRS>EPSG:26912</SRS>' +
+'      <SRS>EPSG:26913</SRS>' +
+'      <SRS>EPSG:26914</SRS>' +
+'      <SRS>EPSG:26915</SRS>' +
+'      <SRS>EPSG:26916</SRS>' +
+'      <SRS>EPSG:26917</SRS>' +
+'      <SRS>EPSG:26918</SRS>' +
+'      <SRS>EPSG:26919</SRS>' +
+'      <SRS>EPSG:26920</SRS>' +
+'      <SRS>EPSG:26921</SRS>' +
+'      <SRS>EPSG:26922</SRS>' +
+'      <SRS>EPSG:26923</SRS>' +
+'      <SRS>EPSG:26929</SRS>' +
+'      <SRS>EPSG:26930</SRS>' +
+'      <SRS>EPSG:26931</SRS>' +
+'      <SRS>EPSG:26932</SRS>' +
+'      <SRS>EPSG:26933</SRS>' +
+'      <SRS>EPSG:26934</SRS>' +
+'      <SRS>EPSG:26935</SRS>' +
+'      <SRS>EPSG:26936</SRS>' +
+'      <SRS>EPSG:26937</SRS>' +
+'      <SRS>EPSG:26938</SRS>' +
+'      <SRS>EPSG:26939</SRS>' +
+'      <SRS>EPSG:26940</SRS>' +
+'      <SRS>EPSG:26941</SRS>' +
+'      <SRS>EPSG:26942</SRS>' +
+'      <SRS>EPSG:26943</SRS>' +
+'      <SRS>EPSG:26944</SRS>' +
+'      <SRS>EPSG:26945</SRS>' +
+'      <SRS>EPSG:26946</SRS>' +
+'      <SRS>EPSG:26948</SRS>' +
+'      <SRS>EPSG:26949</SRS>' +
+'      <SRS>EPSG:26950</SRS>' +
+'      <SRS>EPSG:26951</SRS>' +
+'      <SRS>EPSG:26952</SRS>' +
+'      <SRS>EPSG:26953</SRS>' +
+'      <SRS>EPSG:26954</SRS>' +
+'      <SRS>EPSG:26955</SRS>' +
+'      <SRS>EPSG:26956</SRS>' +
+'      <SRS>EPSG:26957</SRS>' +
+'      <SRS>EPSG:26958</SRS>' +
+'      <SRS>EPSG:26959</SRS>' +
+'      <SRS>EPSG:26960</SRS>' +
+'      <SRS>EPSG:26961</SRS>' +
+'      <SRS>EPSG:26962</SRS>' +
+'      <SRS>EPSG:26963</SRS>' +
+'      <SRS>EPSG:26964</SRS>' +
+'      <SRS>EPSG:26965</SRS>' +
+'      <SRS>EPSG:26966</SRS>' +
+'      <SRS>EPSG:26967</SRS>' +
+'      <SRS>EPSG:26968</SRS>' +
+'      <SRS>EPSG:26969</SRS>' +
+'      <SRS>EPSG:26970</SRS>' +
+'      <SRS>EPSG:26971</SRS>' +
+'      <SRS>EPSG:26972</SRS>' +
+'      <SRS>EPSG:26973</SRS>' +
+'      <SRS>EPSG:26974</SRS>' +
+'      <SRS>EPSG:26975</SRS>' +
+'      <SRS>EPSG:26976</SRS>' +
+'      <SRS>EPSG:26977</SRS>' +
+'      <SRS>EPSG:26978</SRS>' +
+'      <SRS>EPSG:26979</SRS>' +
+'      <SRS>EPSG:26980</SRS>' +
+'      <SRS>EPSG:26981</SRS>' +
+'      <SRS>EPSG:26982</SRS>' +
+'      <SRS>EPSG:26983</SRS>' +
+'      <SRS>EPSG:26984</SRS>' +
+'      <SRS>EPSG:26985</SRS>' +
+'      <SRS>EPSG:26986</SRS>' +
+'      <SRS>EPSG:26987</SRS>' +
+'      <SRS>EPSG:26988</SRS>' +
+'      <SRS>EPSG:26989</SRS>' +
+'      <SRS>EPSG:26990</SRS>' +
+'      <SRS>EPSG:26991</SRS>' +
+'      <SRS>EPSG:26992</SRS>' +
+'      <SRS>EPSG:26993</SRS>' +
+'      <SRS>EPSG:26994</SRS>' +
+'      <SRS>EPSG:26995</SRS>' +
+'      <SRS>EPSG:26996</SRS>' +
+'      <SRS>EPSG:26997</SRS>' +
+'      <SRS>EPSG:26998</SRS>' +
+'      <SRS>EPSG:27037</SRS>' +
+'      <SRS>EPSG:27038</SRS>' +
+'      <SRS>EPSG:27039</SRS>' +
+'      <SRS>EPSG:27040</SRS>' +
+'      <SRS>EPSG:27120</SRS>' +
+'      <SRS>EPSG:27200</SRS>' +
+'      <SRS>EPSG:27205</SRS>' +
+'      <SRS>EPSG:27206</SRS>' +
+'      <SRS>EPSG:27207</SRS>' +
+'      <SRS>EPSG:27208</SRS>' +
+'      <SRS>EPSG:27209</SRS>' +
+'      <SRS>EPSG:27210</SRS>' +
+'      <SRS>EPSG:27211</SRS>' +
+'      <SRS>EPSG:27212</SRS>' +
+'      <SRS>EPSG:27213</SRS>' +
+'      <SRS>EPSG:27214</SRS>' +
+'      <SRS>EPSG:27215</SRS>' +
+'      <SRS>EPSG:27216</SRS>' +
+'      <SRS>EPSG:27217</SRS>' +
+'      <SRS>EPSG:27218</SRS>' +
+'      <SRS>EPSG:27219</SRS>' +
+'      <SRS>EPSG:27220</SRS>' +
+'      <SRS>EPSG:27221</SRS>' +
+'      <SRS>EPSG:27222</SRS>' +
+'      <SRS>EPSG:27223</SRS>' +
+'      <SRS>EPSG:27224</SRS>' +
+'      <SRS>EPSG:27225</SRS>' +
+'      <SRS>EPSG:27226</SRS>' +
+'      <SRS>EPSG:27227</SRS>' +
+'      <SRS>EPSG:27228</SRS>' +
+'      <SRS>EPSG:27229</SRS>' +
+'      <SRS>EPSG:27230</SRS>' +
+'      <SRS>EPSG:27231</SRS>' +
+'      <SRS>EPSG:27232</SRS>' +
+'      <SRS>EPSG:27258</SRS>' +
+'      <SRS>EPSG:27259</SRS>' +
+'      <SRS>EPSG:27260</SRS>' +
+'      <SRS>EPSG:27291</SRS>' +
+'      <SRS>EPSG:27292</SRS>' +
+'      <SRS>EPSG:27391</SRS>' +
+'      <SRS>EPSG:27392</SRS>' +
+'      <SRS>EPSG:27393</SRS>' +
+'      <SRS>EPSG:27394</SRS>' +
+'      <SRS>EPSG:27395</SRS>' +
+'      <SRS>EPSG:27396</SRS>' +
+'      <SRS>EPSG:27397</SRS>' +
+'      <SRS>EPSG:27398</SRS>' +
+'      <SRS>EPSG:27429</SRS>' +
+'      <SRS>EPSG:27492</SRS>' +
+'      <SRS>EPSG:27500</SRS>' +
+'      <SRS>EPSG:27561</SRS>' +
+'      <SRS>EPSG:27562</SRS>' +
+'      <SRS>EPSG:27563</SRS>' +
+'      <SRS>EPSG:27564</SRS>' +
+'      <SRS>EPSG:27571</SRS>' +
+'      <SRS>EPSG:27572</SRS>' +
+'      <SRS>EPSG:27573</SRS>' +
+'      <SRS>EPSG:27574</SRS>' +
+'      <SRS>EPSG:27581</SRS>' +
+'      <SRS>EPSG:27582</SRS>' +
+'      <SRS>EPSG:27583</SRS>' +
+'      <SRS>EPSG:27584</SRS>' +
+'      <SRS>EPSG:27591</SRS>' +
+'      <SRS>EPSG:27592</SRS>' +
+'      <SRS>EPSG:27593</SRS>' +
+'      <SRS>EPSG:27594</SRS>' +
+'      <SRS>EPSG:27700</SRS>' +
+'      <SRS>EPSG:28191</SRS>' +
+'      <SRS>EPSG:28192</SRS>' +
+'      <SRS>EPSG:28193</SRS>' +
+'      <SRS>EPSG:28232</SRS>' +
+'      <SRS>EPSG:28348</SRS>' +
+'      <SRS>EPSG:28349</SRS>' +
+'      <SRS>EPSG:28350</SRS>' +
+'      <SRS>EPSG:28351</SRS>' +
+'      <SRS>EPSG:28352</SRS>' +
+'      <SRS>EPSG:28353</SRS>' +
+'      <SRS>EPSG:28354</SRS>' +
+'      <SRS>EPSG:28355</SRS>' +
+'      <SRS>EPSG:28356</SRS>' +
+'      <SRS>EPSG:28357</SRS>' +
+'      <SRS>EPSG:28358</SRS>' +
+'      <SRS>EPSG:28402</SRS>' +
+'      <SRS>EPSG:28403</SRS>' +
+'      <SRS>EPSG:28404</SRS>' +
+'      <SRS>EPSG:28405</SRS>' +
+'      <SRS>EPSG:28406</SRS>' +
+'      <SRS>EPSG:28407</SRS>' +
+'      <SRS>EPSG:28408</SRS>' +
+'      <SRS>EPSG:28409</SRS>' +
+'      <SRS>EPSG:28410</SRS>' +
+'      <SRS>EPSG:28411</SRS>' +
+'      <SRS>EPSG:28412</SRS>' +
+'      <SRS>EPSG:28413</SRS>' +
+'      <SRS>EPSG:28414</SRS>' +
+'      <SRS>EPSG:28415</SRS>' +
+'      <SRS>EPSG:28416</SRS>' +
+'      <SRS>EPSG:28417</SRS>' +
+'      <SRS>EPSG:28418</SRS>' +
+'      <SRS>EPSG:28419</SRS>' +
+'      <SRS>EPSG:28420</SRS>' +
+'      <SRS>EPSG:28421</SRS>' +
+'      <SRS>EPSG:28422</SRS>' +
+'      <SRS>EPSG:28423</SRS>' +
+'      <SRS>EPSG:28424</SRS>' +
+'      <SRS>EPSG:28425</SRS>' +
+'      <SRS>EPSG:28426</SRS>' +
+'      <SRS>EPSG:28427</SRS>' +
+'      <SRS>EPSG:28428</SRS>' +
+'      <SRS>EPSG:28429</SRS>' +
+'      <SRS>EPSG:28430</SRS>' +
+'      <SRS>EPSG:28431</SRS>' +
+'      <SRS>EPSG:28432</SRS>' +
+'      <SRS>EPSG:28462</SRS>' +
+'      <SRS>EPSG:28463</SRS>' +
+'      <SRS>EPSG:28464</SRS>' +
+'      <SRS>EPSG:28465</SRS>' +
+'      <SRS>EPSG:28466</SRS>' +
+'      <SRS>EPSG:28467</SRS>' +
+'      <SRS>EPSG:28468</SRS>' +
+'      <SRS>EPSG:28469</SRS>' +
+'      <SRS>EPSG:28470</SRS>' +
+'      <SRS>EPSG:28471</SRS>' +
+'      <SRS>EPSG:28472</SRS>' +
+'      <SRS>EPSG:28473</SRS>' +
+'      <SRS>EPSG:28474</SRS>' +
+'      <SRS>EPSG:28475</SRS>' +
+'      <SRS>EPSG:28476</SRS>' +
+'      <SRS>EPSG:28477</SRS>' +
+'      <SRS>EPSG:28478</SRS>' +
+'      <SRS>EPSG:28479</SRS>' +
+'      <SRS>EPSG:28480</SRS>' +
+'      <SRS>EPSG:28481</SRS>' +
+'      <SRS>EPSG:28482</SRS>' +
+'      <SRS>EPSG:28483</SRS>' +
+'      <SRS>EPSG:28484</SRS>' +
+'      <SRS>EPSG:28485</SRS>' +
+'      <SRS>EPSG:28486</SRS>' +
+'      <SRS>EPSG:28487</SRS>' +
+'      <SRS>EPSG:28488</SRS>' +
+'      <SRS>EPSG:28489</SRS>' +
+'      <SRS>EPSG:28490</SRS>' +
+'      <SRS>EPSG:28491</SRS>' +
+'      <SRS>EPSG:28492</SRS>' +
+'      <SRS>EPSG:28600</SRS>' +
+'      <SRS>EPSG:28991</SRS>' +
+'      <SRS>EPSG:28992</SRS>' +
+'      <SRS>EPSG:29100</SRS>' +
+'      <SRS>EPSG:29101</SRS>' +
+'      <SRS>EPSG:29118</SRS>' +
+'      <SRS>EPSG:29119</SRS>' +
+'      <SRS>EPSG:29120</SRS>' +
+'      <SRS>EPSG:29121</SRS>' +
+'      <SRS>EPSG:29122</SRS>' +
+'      <SRS>EPSG:29168</SRS>' +
+'      <SRS>EPSG:29169</SRS>' +
+'      <SRS>EPSG:29170</SRS>' +
+'      <SRS>EPSG:29171</SRS>' +
+'      <SRS>EPSG:29172</SRS>' +
+'      <SRS>EPSG:29177</SRS>' +
+'      <SRS>EPSG:29178</SRS>' +
+'      <SRS>EPSG:29179</SRS>' +
+'      <SRS>EPSG:29180</SRS>' +
+'      <SRS>EPSG:29181</SRS>' +
+'      <SRS>EPSG:29182</SRS>' +
+'      <SRS>EPSG:29183</SRS>' +
+'      <SRS>EPSG:29184</SRS>' +
+'      <SRS>EPSG:29185</SRS>' +
+'      <SRS>EPSG:29187</SRS>' +
+'      <SRS>EPSG:29188</SRS>' +
+'      <SRS>EPSG:29189</SRS>' +
+'      <SRS>EPSG:29190</SRS>' +
+'      <SRS>EPSG:29191</SRS>' +
+'      <SRS>EPSG:29192</SRS>' +
+'      <SRS>EPSG:29193</SRS>' +
+'      <SRS>EPSG:29194</SRS>' +
+'      <SRS>EPSG:29195</SRS>' +
+'      <SRS>EPSG:29220</SRS>' +
+'      <SRS>EPSG:29221</SRS>' +
+'      <SRS>EPSG:29333</SRS>' +
+'      <SRS>EPSG:29371</SRS>' +
+'      <SRS>EPSG:29373</SRS>' +
+'      <SRS>EPSG:29375</SRS>' +
+'      <SRS>EPSG:29377</SRS>' +
+'      <SRS>EPSG:29379</SRS>' +
+'      <SRS>EPSG:29381</SRS>' +
+'      <SRS>EPSG:29383</SRS>' +
+'      <SRS>EPSG:29385</SRS>' +
+'      <SRS>EPSG:29635</SRS>' +
+'      <SRS>EPSG:29636</SRS>' +
+'      <SRS>EPSG:29700</SRS>' +
+'      <SRS>EPSG:29701</SRS>' +
+'      <SRS>EPSG:29702</SRS>' +
+'      <SRS>EPSG:29738</SRS>' +
+'      <SRS>EPSG:29739</SRS>' +
+'      <SRS>EPSG:29849</SRS>' +
+'      <SRS>EPSG:29850</SRS>' +
+'      <SRS>EPSG:29871</SRS>' +
+'      <SRS>EPSG:29872</SRS>' +
+'      <SRS>EPSG:29873</SRS>' +
+'      <SRS>EPSG:29900</SRS>' +
+'      <SRS>EPSG:29901</SRS>' +
+'      <SRS>EPSG:29902</SRS>' +
+'      <SRS>EPSG:29903</SRS>' +
+'      <SRS>EPSG:30161</SRS>' +
+'      <SRS>EPSG:30162</SRS>' +
+'      <SRS>EPSG:30163</SRS>' +
+'      <SRS>EPSG:30164</SRS>' +
+'      <SRS>EPSG:30165</SRS>' +
+'      <SRS>EPSG:30166</SRS>' +
+'      <SRS>EPSG:30167</SRS>' +
+'      <SRS>EPSG:30168</SRS>' +
+'      <SRS>EPSG:30169</SRS>' +
+'      <SRS>EPSG:30170</SRS>' +
+'      <SRS>EPSG:30171</SRS>' +
+'      <SRS>EPSG:30172</SRS>' +
+'      <SRS>EPSG:30173</SRS>' +
+'      <SRS>EPSG:30174</SRS>' +
+'      <SRS>EPSG:30175</SRS>' +
+'      <SRS>EPSG:30176</SRS>' +
+'      <SRS>EPSG:30177</SRS>' +
+'      <SRS>EPSG:30178</SRS>' +
+'      <SRS>EPSG:30179</SRS>' +
+'      <SRS>EPSG:30200</SRS>' +
+'      <SRS>EPSG:30339</SRS>' +
+'      <SRS>EPSG:30340</SRS>' +
+'      <SRS>EPSG:30491</SRS>' +
+'      <SRS>EPSG:30492</SRS>' +
+'      <SRS>EPSG:30493</SRS>' +
+'      <SRS>EPSG:30494</SRS>' +
+'      <SRS>EPSG:30729</SRS>' +
+'      <SRS>EPSG:30730</SRS>' +
+'      <SRS>EPSG:30731</SRS>' +
+'      <SRS>EPSG:30732</SRS>' +
+'      <SRS>EPSG:30791</SRS>' +
+'      <SRS>EPSG:30792</SRS>' +
+'      <SRS>EPSG:30800</SRS>' +
+'      <SRS>EPSG:31028</SRS>' +
+'      <SRS>EPSG:31121</SRS>' +
+'      <SRS>EPSG:31154</SRS>' +
+'      <SRS>EPSG:31170</SRS>' +
+'      <SRS>EPSG:31171</SRS>' +
+'      <SRS>EPSG:31251</SRS>' +
+'      <SRS>EPSG:31252</SRS>' +
+'      <SRS>EPSG:31253</SRS>' +
+'      <SRS>EPSG:31254</SRS>' +
+'      <SRS>EPSG:31255</SRS>' +
+'      <SRS>EPSG:31256</SRS>' +
+'      <SRS>EPSG:31257</SRS>' +
+'      <SRS>EPSG:31258</SRS>' +
+'      <SRS>EPSG:31259</SRS>' +
+'      <SRS>EPSG:31265</SRS>' +
+'      <SRS>EPSG:31266</SRS>' +
+'      <SRS>EPSG:31267</SRS>' +
+'      <SRS>EPSG:31268</SRS>' +
+'      <SRS>EPSG:31275</SRS>' +
+'      <SRS>EPSG:31276</SRS>' +
+'      <SRS>EPSG:31277</SRS>' +
+'      <SRS>EPSG:31278</SRS>' +
+'      <SRS>EPSG:31279</SRS>' +
+'      <SRS>EPSG:31281</SRS>' +
+'      <SRS>EPSG:31282</SRS>' +
+'      <SRS>EPSG:31283</SRS>' +
+'      <SRS>EPSG:31284</SRS>' +
+'      <SRS>EPSG:31285</SRS>' +
+'      <SRS>EPSG:31286</SRS>' +
+'      <SRS>EPSG:31287</SRS>' +
+'      <SRS>EPSG:31288</SRS>' +
+'      <SRS>EPSG:31289</SRS>' +
+'      <SRS>EPSG:31290</SRS>' +
+'      <SRS>EPSG:31291</SRS>' +
+'      <SRS>EPSG:31292</SRS>' +
+'      <SRS>EPSG:31293</SRS>' +
+'      <SRS>EPSG:31294</SRS>' +
+'      <SRS>EPSG:31295</SRS>' +
+'      <SRS>EPSG:31296</SRS>' +
+'      <SRS>EPSG:31297</SRS>' +
+'      <SRS>EPSG:31300</SRS>' +
+'      <SRS>EPSG:31370</SRS>' +
+'      <SRS>EPSG:31461</SRS>' +
+'      <SRS>EPSG:31462</SRS>' +
+'      <SRS>EPSG:31463</SRS>' +
+'      <SRS>EPSG:31464</SRS>' +
+'      <SRS>EPSG:31465</SRS>' +
+'      <SRS>EPSG:31466</SRS>' +
+'      <SRS>EPSG:31467</SRS>' +
+'      <SRS>EPSG:31468</SRS>' +
+'      <SRS>EPSG:31469</SRS>' +
+'      <SRS>EPSG:31528</SRS>' +
+'      <SRS>EPSG:31529</SRS>' +
+'      <SRS>EPSG:31600</SRS>' +
+'      <SRS>EPSG:31700</SRS>' +
+'      <SRS>EPSG:31838</SRS>' +
+'      <SRS>EPSG:31839</SRS>' +
+'      <SRS>EPSG:31900</SRS>' +
+'      <SRS>EPSG:31901</SRS>' +
+'      <SRS>EPSG:31965</SRS>' +
+'      <SRS>EPSG:31966</SRS>' +
+'      <SRS>EPSG:31967</SRS>' +
+'      <SRS>EPSG:31968</SRS>' +
+'      <SRS>EPSG:31969</SRS>' +
+'      <SRS>EPSG:31970</SRS>' +
+'      <SRS>EPSG:31971</SRS>' +
+'      <SRS>EPSG:31972</SRS>' +
+'      <SRS>EPSG:31973</SRS>' +
+'      <SRS>EPSG:31974</SRS>' +
+'      <SRS>EPSG:31975</SRS>' +
+'      <SRS>EPSG:31976</SRS>' +
+'      <SRS>EPSG:31977</SRS>' +
+'      <SRS>EPSG:31978</SRS>' +
+'      <SRS>EPSG:31979</SRS>' +
+'      <SRS>EPSG:31980</SRS>' +
+'      <SRS>EPSG:31981</SRS>' +
+'      <SRS>EPSG:31982</SRS>' +
+'      <SRS>EPSG:31983</SRS>' +
+'      <SRS>EPSG:31984</SRS>' +
+'      <SRS>EPSG:31985</SRS>' +
+'      <SRS>EPSG:31986</SRS>' +
+'      <SRS>EPSG:31987</SRS>' +
+'      <SRS>EPSG:31988</SRS>' +
+'      <SRS>EPSG:31989</SRS>' +
+'      <SRS>EPSG:31990</SRS>' +
+'      <SRS>EPSG:31991</SRS>' +
+'      <SRS>EPSG:31992</SRS>' +
+'      <SRS>EPSG:31993</SRS>' +
+'      <SRS>EPSG:31994</SRS>' +
+'      <SRS>EPSG:31995</SRS>' +
+'      <SRS>EPSG:31996</SRS>' +
+'      <SRS>EPSG:31997</SRS>' +
+'      <SRS>EPSG:31998</SRS>' +
+'      <SRS>EPSG:31999</SRS>' +
+'      <SRS>EPSG:32000</SRS>' +
+'      <SRS>EPSG:32001</SRS>' +
+'      <SRS>EPSG:32002</SRS>' +
+'      <SRS>EPSG:32003</SRS>' +
+'      <SRS>EPSG:32005</SRS>' +
+'      <SRS>EPSG:32006</SRS>' +
+'      <SRS>EPSG:32007</SRS>' +
+'      <SRS>EPSG:32008</SRS>' +
+'      <SRS>EPSG:32009</SRS>' +
+'      <SRS>EPSG:32010</SRS>' +
+'      <SRS>EPSG:32011</SRS>' +
+'      <SRS>EPSG:32012</SRS>' +
+'      <SRS>EPSG:32013</SRS>' +
+'      <SRS>EPSG:32014</SRS>' +
+'      <SRS>EPSG:32015</SRS>' +
+'      <SRS>EPSG:32016</SRS>' +
+'      <SRS>EPSG:32017</SRS>' +
+'      <SRS>EPSG:32018</SRS>' +
+'      <SRS>EPSG:32019</SRS>' +
+'      <SRS>EPSG:32020</SRS>' +
+'      <SRS>EPSG:32021</SRS>' +
+'      <SRS>EPSG:32022</SRS>' +
+'      <SRS>EPSG:32023</SRS>' +
+'      <SRS>EPSG:32024</SRS>' +
+'      <SRS>EPSG:32025</SRS>' +
+'      <SRS>EPSG:32026</SRS>' +
+'      <SRS>EPSG:32027</SRS>' +
+'      <SRS>EPSG:32028</SRS>' +
+'      <SRS>EPSG:32029</SRS>' +
+'      <SRS>EPSG:32030</SRS>' +
+'      <SRS>EPSG:32031</SRS>' +
+'      <SRS>EPSG:32033</SRS>' +
+'      <SRS>EPSG:32034</SRS>' +
+'      <SRS>EPSG:32035</SRS>' +
+'      <SRS>EPSG:32036</SRS>' +
+'      <SRS>EPSG:32037</SRS>' +
+'      <SRS>EPSG:32038</SRS>' +
+'      <SRS>EPSG:32039</SRS>' +
+'      <SRS>EPSG:32040</SRS>' +
+'      <SRS>EPSG:32041</SRS>' +
+'      <SRS>EPSG:32042</SRS>' +
+'      <SRS>EPSG:32043</SRS>' +
+'      <SRS>EPSG:32044</SRS>' +
+'      <SRS>EPSG:32045</SRS>' +
+'      <SRS>EPSG:32046</SRS>' +
+'      <SRS>EPSG:32047</SRS>' +
+'      <SRS>EPSG:32048</SRS>' +
+'      <SRS>EPSG:32049</SRS>' +
+'      <SRS>EPSG:32050</SRS>' +
+'      <SRS>EPSG:32051</SRS>' +
+'      <SRS>EPSG:32052</SRS>' +
+'      <SRS>EPSG:32053</SRS>' +
+'      <SRS>EPSG:32054</SRS>' +
+'      <SRS>EPSG:32055</SRS>' +
+'      <SRS>EPSG:32056</SRS>' +
+'      <SRS>EPSG:32057</SRS>' +
+'      <SRS>EPSG:32058</SRS>' +
+'      <SRS>EPSG:32061</SRS>' +
+'      <SRS>EPSG:32062</SRS>' +
+'      <SRS>EPSG:32064</SRS>' +
+'      <SRS>EPSG:32065</SRS>' +
+'      <SRS>EPSG:32066</SRS>' +
+'      <SRS>EPSG:32067</SRS>' +
+'      <SRS>EPSG:32074</SRS>' +
+'      <SRS>EPSG:32075</SRS>' +
+'      <SRS>EPSG:32076</SRS>' +
+'      <SRS>EPSG:32077</SRS>' +
+'      <SRS>EPSG:32081</SRS>' +
+'      <SRS>EPSG:32082</SRS>' +
+'      <SRS>EPSG:32083</SRS>' +
+'      <SRS>EPSG:32084</SRS>' +
+'      <SRS>EPSG:32085</SRS>' +
+'      <SRS>EPSG:32086</SRS>' +
+'      <SRS>EPSG:32098</SRS>' +
+'      <SRS>EPSG:32099</SRS>' +
+'      <SRS>EPSG:32100</SRS>' +
+'      <SRS>EPSG:32104</SRS>' +
+'      <SRS>EPSG:32107</SRS>' +
+'      <SRS>EPSG:32108</SRS>' +
+'      <SRS>EPSG:32109</SRS>' +
+'      <SRS>EPSG:32110</SRS>' +
+'      <SRS>EPSG:32111</SRS>' +
+'      <SRS>EPSG:32112</SRS>' +
+'      <SRS>EPSG:32113</SRS>' +
+'      <SRS>EPSG:32114</SRS>' +
+'      <SRS>EPSG:32115</SRS>' +
+'      <SRS>EPSG:32116</SRS>' +
+'      <SRS>EPSG:32117</SRS>' +
+'      <SRS>EPSG:32118</SRS>' +
+'      <SRS>EPSG:32119</SRS>' +
+'      <SRS>EPSG:32120</SRS>' +
+'      <SRS>EPSG:32121</SRS>' +
+'      <SRS>EPSG:32122</SRS>' +
+'      <SRS>EPSG:32123</SRS>' +
+'      <SRS>EPSG:32124</SRS>' +
+'      <SRS>EPSG:32125</SRS>' +
+'      <SRS>EPSG:32126</SRS>' +
+'      <SRS>EPSG:32127</SRS>' +
+'      <SRS>EPSG:32128</SRS>' +
+'      <SRS>EPSG:32129</SRS>' +
+'      <SRS>EPSG:32130</SRS>' +
+'      <SRS>EPSG:32133</SRS>' +
+'      <SRS>EPSG:32134</SRS>' +
+'      <SRS>EPSG:32135</SRS>' +
+'      <SRS>EPSG:32136</SRS>' +
+'      <SRS>EPSG:32137</SRS>' +
+'      <SRS>EPSG:32138</SRS>' +
+'      <SRS>EPSG:32139</SRS>' +
+'      <SRS>EPSG:32140</SRS>' +
+'      <SRS>EPSG:32141</SRS>' +
+'      <SRS>EPSG:32142</SRS>' +
+'      <SRS>EPSG:32143</SRS>' +
+'      <SRS>EPSG:32144</SRS>' +
+'      <SRS>EPSG:32145</SRS>' +
+'      <SRS>EPSG:32146</SRS>' +
+'      <SRS>EPSG:32147</SRS>' +
+'      <SRS>EPSG:32148</SRS>' +
+'      <SRS>EPSG:32149</SRS>' +
+'      <SRS>EPSG:32150</SRS>' +
+'      <SRS>EPSG:32151</SRS>' +
+'      <SRS>EPSG:32152</SRS>' +
+'      <SRS>EPSG:32153</SRS>' +
+'      <SRS>EPSG:32154</SRS>' +
+'      <SRS>EPSG:32155</SRS>' +
+'      <SRS>EPSG:32156</SRS>' +
+'      <SRS>EPSG:32157</SRS>' +
+'      <SRS>EPSG:32158</SRS>' +
+'      <SRS>EPSG:32161</SRS>' +
+'      <SRS>EPSG:32164</SRS>' +
+'      <SRS>EPSG:32165</SRS>' +
+'      <SRS>EPSG:32166</SRS>' +
+'      <SRS>EPSG:32167</SRS>' +
+'      <SRS>EPSG:32180</SRS>' +
+'      <SRS>EPSG:32181</SRS>' +
+'      <SRS>EPSG:32182</SRS>' +
+'      <SRS>EPSG:32183</SRS>' +
+'      <SRS>EPSG:32184</SRS>' +
+'      <SRS>EPSG:32185</SRS>' +
+'      <SRS>EPSG:32186</SRS>' +
+'      <SRS>EPSG:32187</SRS>' +
+'      <SRS>EPSG:32188</SRS>' +
+'      <SRS>EPSG:32189</SRS>' +
+'      <SRS>EPSG:32190</SRS>' +
+'      <SRS>EPSG:32191</SRS>' +
+'      <SRS>EPSG:32192</SRS>' +
+'      <SRS>EPSG:32193</SRS>' +
+'      <SRS>EPSG:32194</SRS>' +
+'      <SRS>EPSG:32195</SRS>' +
+'      <SRS>EPSG:32196</SRS>' +
+'      <SRS>EPSG:32197</SRS>' +
+'      <SRS>EPSG:32198</SRS>' +
+'      <SRS>EPSG:32199</SRS>' +
+'      <SRS>EPSG:32201</SRS>' +
+'      <SRS>EPSG:32202</SRS>' +
+'      <SRS>EPSG:32203</SRS>' +
+'      <SRS>EPSG:32204</SRS>' +
+'      <SRS>EPSG:32205</SRS>' +
+'      <SRS>EPSG:32206</SRS>' +
+'      <SRS>EPSG:32207</SRS>' +
+'      <SRS>EPSG:32208</SRS>' +
+'      <SRS>EPSG:32209</SRS>' +
+'      <SRS>EPSG:32210</SRS>' +
+'      <SRS>EPSG:32211</SRS>' +
+'      <SRS>EPSG:32212</SRS>' +
+'      <SRS>EPSG:32213</SRS>' +
+'      <SRS>EPSG:32214</SRS>' +
+'      <SRS>EPSG:32215</SRS>' +
+'      <SRS>EPSG:32216</SRS>' +
+'      <SRS>EPSG:32217</SRS>' +
+'      <SRS>EPSG:32218</SRS>' +
+'      <SRS>EPSG:32219</SRS>' +
+'      <SRS>EPSG:32220</SRS>' +
+'      <SRS>EPSG:32221</SRS>' +
+'      <SRS>EPSG:32222</SRS>' +
+'      <SRS>EPSG:32223</SRS>' +
+'      <SRS>EPSG:32224</SRS>' +
+'      <SRS>EPSG:32225</SRS>' +
+'      <SRS>EPSG:32226</SRS>' +
+'      <SRS>EPSG:32227</SRS>' +
+'      <SRS>EPSG:32228</SRS>' +
+'      <SRS>EPSG:32229</SRS>' +
+'      <SRS>EPSG:32230</SRS>' +
+'      <SRS>EPSG:32231</SRS>' +
+'      <SRS>EPSG:32232</SRS>' +
+'      <SRS>EPSG:32233</SRS>' +
+'      <SRS>EPSG:32234</SRS>' +
+'      <SRS>EPSG:32235</SRS>' +
+'      <SRS>EPSG:32236</SRS>' +
+'      <SRS>EPSG:32237</SRS>' +
+'      <SRS>EPSG:32238</SRS>' +
+'      <SRS>EPSG:32239</SRS>' +
+'      <SRS>EPSG:32240</SRS>' +
+'      <SRS>EPSG:32241</SRS>' +
+'      <SRS>EPSG:32242</SRS>' +
+'      <SRS>EPSG:32243</SRS>' +
+'      <SRS>EPSG:32244</SRS>' +
+'      <SRS>EPSG:32245</SRS>' +
+'      <SRS>EPSG:32246</SRS>' +
+'      <SRS>EPSG:32247</SRS>' +
+'      <SRS>EPSG:32248</SRS>' +
+'      <SRS>EPSG:32249</SRS>' +
+'      <SRS>EPSG:32250</SRS>' +
+'      <SRS>EPSG:32251</SRS>' +
+'      <SRS>EPSG:32252</SRS>' +
+'      <SRS>EPSG:32253</SRS>' +
+'      <SRS>EPSG:32254</SRS>' +
+'      <SRS>EPSG:32255</SRS>' +
+'      <SRS>EPSG:32256</SRS>' +
+'      <SRS>EPSG:32257</SRS>' +
+'      <SRS>EPSG:32258</SRS>' +
+'      <SRS>EPSG:32259</SRS>' +
+'      <SRS>EPSG:32260</SRS>' +
+'      <SRS>EPSG:32301</SRS>' +
+'      <SRS>EPSG:32302</SRS>' +
+'      <SRS>EPSG:32303</SRS>' +
+'      <SRS>EPSG:32304</SRS>' +
+'      <SRS>EPSG:32305</SRS>' +
+'      <SRS>EPSG:32306</SRS>' +
+'      <SRS>EPSG:32307</SRS>' +
+'      <SRS>EPSG:32308</SRS>' +
+'      <SRS>EPSG:32309</SRS>' +
+'      <SRS>EPSG:32310</SRS>' +
+'      <SRS>EPSG:32311</SRS>' +
+'      <SRS>EPSG:32312</SRS>' +
+'      <SRS>EPSG:32313</SRS>' +
+'      <SRS>EPSG:32314</SRS>' +
+'      <SRS>EPSG:32315</SRS>' +
+'      <SRS>EPSG:32316</SRS>' +
+'      <SRS>EPSG:32317</SRS>' +
+'      <SRS>EPSG:32318</SRS>' +
+'      <SRS>EPSG:32319</SRS>' +
+'      <SRS>EPSG:32320</SRS>' +
+'      <SRS>EPSG:32321</SRS>' +
+'      <SRS>EPSG:32322</SRS>' +
+'      <SRS>EPSG:32323</SRS>' +
+'      <SRS>EPSG:32324</SRS>' +
+'      <SRS>EPSG:32325</SRS>' +
+'      <SRS>EPSG:32326</SRS>' +
+'      <SRS>EPSG:32327</SRS>' +
+'      <SRS>EPSG:32328</SRS>' +
+'      <SRS>EPSG:32329</SRS>' +
+'      <SRS>EPSG:32330</SRS>' +
+'      <SRS>EPSG:32331</SRS>' +
+'      <SRS>EPSG:32332</SRS>' +
+'      <SRS>EPSG:32333</SRS>' +
+'      <SRS>EPSG:32334</SRS>' +
+'      <SRS>EPSG:32335</SRS>' +
+'      <SRS>EPSG:32336</SRS>' +
+'      <SRS>EPSG:32337</SRS>' +
+'      <SRS>EPSG:32338</SRS>' +
+'      <SRS>EPSG:32339</SRS>' +
+'      <SRS>EPSG:32340</SRS>' +
+'      <SRS>EPSG:32341</SRS>' +
+'      <SRS>EPSG:32342</SRS>' +
+'      <SRS>EPSG:32343</SRS>' +
+'      <SRS>EPSG:32344</SRS>' +
+'      <SRS>EPSG:32345</SRS>' +
+'      <SRS>EPSG:32346</SRS>' +
+'      <SRS>EPSG:32347</SRS>' +
+'      <SRS>EPSG:32348</SRS>' +
+'      <SRS>EPSG:32349</SRS>' +
+'      <SRS>EPSG:32350</SRS>' +
+'      <SRS>EPSG:32351</SRS>' +
+'      <SRS>EPSG:32352</SRS>' +
+'      <SRS>EPSG:32353</SRS>' +
+'      <SRS>EPSG:32354</SRS>' +
+'      <SRS>EPSG:32355</SRS>' +
+'      <SRS>EPSG:32356</SRS>' +
+'      <SRS>EPSG:32357</SRS>' +
+'      <SRS>EPSG:32358</SRS>' +
+'      <SRS>EPSG:32359</SRS>' +
+'      <SRS>EPSG:32360</SRS>' +
+'      <SRS>EPSG:32401</SRS>' +
+'      <SRS>EPSG:32402</SRS>' +
+'      <SRS>EPSG:32403</SRS>' +
+'      <SRS>EPSG:32404</SRS>' +
+'      <SRS>EPSG:32405</SRS>' +
+'      <SRS>EPSG:32406</SRS>' +
+'      <SRS>EPSG:32407</SRS>' +
+'      <SRS>EPSG:32408</SRS>' +
+'      <SRS>EPSG:32409</SRS>' +
+'      <SRS>EPSG:32410</SRS>' +
+'      <SRS>EPSG:32411</SRS>' +
+'      <SRS>EPSG:32412</SRS>' +
+'      <SRS>EPSG:32413</SRS>' +
+'      <SRS>EPSG:32414</SRS>' +
+'      <SRS>EPSG:32415</SRS>' +
+'      <SRS>EPSG:32416</SRS>' +
+'      <SRS>EPSG:32417</SRS>' +
+'      <SRS>EPSG:32418</SRS>' +
+'      <SRS>EPSG:32419</SRS>' +
+'      <SRS>EPSG:32420</SRS>' +
+'      <SRS>EPSG:32421</SRS>' +
+'      <SRS>EPSG:32422</SRS>' +
+'      <SRS>EPSG:32423</SRS>' +
+'      <SRS>EPSG:32424</SRS>' +
+'      <SRS>EPSG:32425</SRS>' +
+'      <SRS>EPSG:32426</SRS>' +
+'      <SRS>EPSG:32427</SRS>' +
+'      <SRS>EPSG:32428</SRS>' +
+'      <SRS>EPSG:32429</SRS>' +
+'      <SRS>EPSG:32430</SRS>' +
+'      <SRS>EPSG:32431</SRS>' +
+'      <SRS>EPSG:32432</SRS>' +
+'      <SRS>EPSG:32433</SRS>' +
+'      <SRS>EPSG:32434</SRS>' +
+'      <SRS>EPSG:32435</SRS>' +
+'      <SRS>EPSG:32436</SRS>' +
+'      <SRS>EPSG:32437</SRS>' +
+'      <SRS>EPSG:32438</SRS>' +
+'      <SRS>EPSG:32439</SRS>' +
+'      <SRS>EPSG:32440</SRS>' +
+'      <SRS>EPSG:32441</SRS>' +
+'      <SRS>EPSG:32442</SRS>' +
+'      <SRS>EPSG:32443</SRS>' +
+'      <SRS>EPSG:32444</SRS>' +
+'      <SRS>EPSG:32445</SRS>' +
+'      <SRS>EPSG:32446</SRS>' +
+'      <SRS>EPSG:32447</SRS>' +
+'      <SRS>EPSG:32448</SRS>' +
+'      <SRS>EPSG:32449</SRS>' +
+'      <SRS>EPSG:32450</SRS>' +
+'      <SRS>EPSG:32451</SRS>' +
+'      <SRS>EPSG:32452</SRS>' +
+'      <SRS>EPSG:32453</SRS>' +
+'      <SRS>EPSG:32454</SRS>' +
+'      <SRS>EPSG:32455</SRS>' +
+'      <SRS>EPSG:32456</SRS>' +
+'      <SRS>EPSG:32457</SRS>' +
+'      <SRS>EPSG:32458</SRS>' +
+'      <SRS>EPSG:32459</SRS>' +
+'      <SRS>EPSG:32460</SRS>' +
+'      <SRS>EPSG:32501</SRS>' +
+'      <SRS>EPSG:32502</SRS>' +
+'      <SRS>EPSG:32503</SRS>' +
+'      <SRS>EPSG:32504</SRS>' +
+'      <SRS>EPSG:32505</SRS>' +
+'      <SRS>EPSG:32506</SRS>' +
+'      <SRS>EPSG:32507</SRS>' +
+'      <SRS>EPSG:32508</SRS>' +
+'      <SRS>EPSG:32509</SRS>' +
+'      <SRS>EPSG:32510</SRS>' +
+'      <SRS>EPSG:32511</SRS>' +
+'      <SRS>EPSG:32512</SRS>' +
+'      <SRS>EPSG:32513</SRS>' +
+'      <SRS>EPSG:32514</SRS>' +
+'      <SRS>EPSG:32515</SRS>' +
+'      <SRS>EPSG:32516</SRS>' +
+'      <SRS>EPSG:32517</SRS>' +
+'      <SRS>EPSG:32518</SRS>' +
+'      <SRS>EPSG:32519</SRS>' +
+'      <SRS>EPSG:32520</SRS>' +
+'      <SRS>EPSG:32521</SRS>' +
+'      <SRS>EPSG:32522</SRS>' +
+'      <SRS>EPSG:32523</SRS>' +
+'      <SRS>EPSG:32524</SRS>' +
+'      <SRS>EPSG:32525</SRS>' +
+'      <SRS>EPSG:32526</SRS>' +
+'      <SRS>EPSG:32527</SRS>' +
+'      <SRS>EPSG:32528</SRS>' +
+'      <SRS>EPSG:32529</SRS>' +
+'      <SRS>EPSG:32530</SRS>' +
+'      <SRS>EPSG:32531</SRS>' +
+'      <SRS>EPSG:32532</SRS>' +
+'      <SRS>EPSG:32533</SRS>' +
+'      <SRS>EPSG:32534</SRS>' +
+'      <SRS>EPSG:32535</SRS>' +
+'      <SRS>EPSG:32536</SRS>' +
+'      <SRS>EPSG:32537</SRS>' +
+'      <SRS>EPSG:32538</SRS>' +
+'      <SRS>EPSG:32539</SRS>' +
+'      <SRS>EPSG:32540</SRS>' +
+'      <SRS>EPSG:32541</SRS>' +
+'      <SRS>EPSG:32542</SRS>' +
+'      <SRS>EPSG:32543</SRS>' +
+'      <SRS>EPSG:32544</SRS>' +
+'      <SRS>EPSG:32545</SRS>' +
+'      <SRS>EPSG:32546</SRS>' +
+'      <SRS>EPSG:32547</SRS>' +
+'      <SRS>EPSG:32548</SRS>' +
+'      <SRS>EPSG:32549</SRS>' +
+'      <SRS>EPSG:32550</SRS>' +
+'      <SRS>EPSG:32551</SRS>' +
+'      <SRS>EPSG:32552</SRS>' +
+'      <SRS>EPSG:32553</SRS>' +
+'      <SRS>EPSG:32554</SRS>' +
+'      <SRS>EPSG:32555</SRS>' +
+'      <SRS>EPSG:32556</SRS>' +
+'      <SRS>EPSG:32557</SRS>' +
+'      <SRS>EPSG:32558</SRS>' +
+'      <SRS>EPSG:32559</SRS>' +
+'      <SRS>EPSG:32560</SRS>' +
+'      <SRS>EPSG:32600</SRS>' +
+'      <SRS>EPSG:32601</SRS>' +
+'      <SRS>EPSG:32602</SRS>' +
+'      <SRS>EPSG:32603</SRS>' +
+'      <SRS>EPSG:32604</SRS>' +
+'      <SRS>EPSG:32605</SRS>' +
+'      <SRS>EPSG:32606</SRS>' +
+'      <SRS>EPSG:32607</SRS>' +
+'      <SRS>EPSG:32608</SRS>' +
+'      <SRS>EPSG:32609</SRS>' +
+'      <SRS>EPSG:32610</SRS>' +
+'      <SRS>EPSG:32611</SRS>' +
+'      <SRS>EPSG:32612</SRS>' +
+'      <SRS>EPSG:32613</SRS>' +
+'      <SRS>EPSG:32614</SRS>' +
+'      <SRS>EPSG:32615</SRS>' +
+'      <SRS>EPSG:32616</SRS>' +
+'      <SRS>EPSG:32617</SRS>' +
+'      <SRS>EPSG:32618</SRS>' +
+'      <SRS>EPSG:32619</SRS>' +
+'      <SRS>EPSG:32620</SRS>' +
+'      <SRS>EPSG:32621</SRS>' +
+'      <SRS>EPSG:32622</SRS>' +
+'      <SRS>EPSG:32623</SRS>' +
+'      <SRS>EPSG:32624</SRS>' +
+'      <SRS>EPSG:32625</SRS>' +
+'      <SRS>EPSG:32626</SRS>' +
+'      <SRS>EPSG:32627</SRS>' +
+'      <SRS>EPSG:32628</SRS>' +
+'      <SRS>EPSG:32629</SRS>' +
+'      <SRS>EPSG:32630</SRS>' +
+'      <SRS>EPSG:32631</SRS>' +
+'      <SRS>EPSG:32632</SRS>' +
+'      <SRS>EPSG:32633</SRS>' +
+'      <SRS>EPSG:32634</SRS>' +
+'      <SRS>EPSG:32635</SRS>' +
+'      <SRS>EPSG:32636</SRS>' +
+'      <SRS>EPSG:32637</SRS>' +
+'      <SRS>EPSG:32638</SRS>' +
+'      <SRS>EPSG:32639</SRS>' +
+'      <SRS>EPSG:32640</SRS>' +
+'      <SRS>EPSG:32641</SRS>' +
+'      <SRS>EPSG:32642</SRS>' +
+'      <SRS>EPSG:32643</SRS>' +
+'      <SRS>EPSG:32644</SRS>' +
+'      <SRS>EPSG:32645</SRS>' +
+'      <SRS>EPSG:32646</SRS>' +
+'      <SRS>EPSG:32647</SRS>' +
+'      <SRS>EPSG:32648</SRS>' +
+'      <SRS>EPSG:32649</SRS>' +
+'      <SRS>EPSG:32650</SRS>' +
+'      <SRS>EPSG:32651</SRS>' +
+'      <SRS>EPSG:32652</SRS>' +
+'      <SRS>EPSG:32653</SRS>' +
+'      <SRS>EPSG:32654</SRS>' +
+'      <SRS>EPSG:32655</SRS>' +
+'      <SRS>EPSG:32656</SRS>' +
+'      <SRS>EPSG:32657</SRS>' +
+'      <SRS>EPSG:32658</SRS>' +
+'      <SRS>EPSG:32659</SRS>' +
+'      <SRS>EPSG:32660</SRS>' +
+'      <SRS>EPSG:32661</SRS>' +
+'      <SRS>EPSG:32662</SRS>' +
+'      <SRS>EPSG:32664</SRS>' +
+'      <SRS>EPSG:32665</SRS>' +
+'      <SRS>EPSG:32666</SRS>' +
+'      <SRS>EPSG:32667</SRS>' +
+'      <SRS>EPSG:32700</SRS>' +
+'      <SRS>EPSG:32701</SRS>' +
+'      <SRS>EPSG:32702</SRS>' +
+'      <SRS>EPSG:32703</SRS>' +
+'      <SRS>EPSG:32704</SRS>' +
+'      <SRS>EPSG:32705</SRS>' +
+'      <SRS>EPSG:32706</SRS>' +
+'      <SRS>EPSG:32707</SRS>' +
+'      <SRS>EPSG:32708</SRS>' +
+'      <SRS>EPSG:32709</SRS>' +
+'      <SRS>EPSG:32710</SRS>' +
+'      <SRS>EPSG:32711</SRS>' +
+'      <SRS>EPSG:32712</SRS>' +
+'      <SRS>EPSG:32713</SRS>' +
+'      <SRS>EPSG:32714</SRS>' +
+'      <SRS>EPSG:32715</SRS>' +
+'      <SRS>EPSG:32716</SRS>' +
+'      <SRS>EPSG:32717</SRS>' +
+'      <SRS>EPSG:32718</SRS>' +
+'      <SRS>EPSG:32719</SRS>' +
+'      <SRS>EPSG:32720</SRS>' +
+'      <SRS>EPSG:32721</SRS>' +
+'      <SRS>EPSG:32722</SRS>' +
+'      <SRS>EPSG:32723</SRS>' +
+'      <SRS>EPSG:32724</SRS>' +
+'      <SRS>EPSG:32725</SRS>' +
+'      <SRS>EPSG:32726</SRS>' +
+'      <SRS>EPSG:32727</SRS>' +
+'      <SRS>EPSG:32728</SRS>' +
+'      <SRS>EPSG:32729</SRS>' +
+'      <SRS>EPSG:32730</SRS>' +
+'      <SRS>EPSG:32731</SRS>' +
+'      <SRS>EPSG:32732</SRS>' +
+'      <SRS>EPSG:32733</SRS>' +
+'      <SRS>EPSG:32734</SRS>' +
+'      <SRS>EPSG:32735</SRS>' +
+'      <SRS>EPSG:32736</SRS>' +
+'      <SRS>EPSG:32737</SRS>' +
+'      <SRS>EPSG:32738</SRS>' +
+'      <SRS>EPSG:32739</SRS>' +
+'      <SRS>EPSG:32740</SRS>' +
+'      <SRS>EPSG:32741</SRS>' +
+'      <SRS>EPSG:32742</SRS>' +
+'      <SRS>EPSG:32743</SRS>' +
+'      <SRS>EPSG:32744</SRS>' +
+'      <SRS>EPSG:32745</SRS>' +
+'      <SRS>EPSG:32746</SRS>' +
+'      <SRS>EPSG:32747</SRS>' +
+'      <SRS>EPSG:32748</SRS>' +
+'      <SRS>EPSG:32749</SRS>' +
+'      <SRS>EPSG:32750</SRS>' +
+'      <SRS>EPSG:32751</SRS>' +
+'      <SRS>EPSG:32752</SRS>' +
+'      <SRS>EPSG:32753</SRS>' +
+'      <SRS>EPSG:32754</SRS>' +
+'      <SRS>EPSG:32755</SRS>' +
+'      <SRS>EPSG:32756</SRS>' +
+'      <SRS>EPSG:32757</SRS>' +
+'      <SRS>EPSG:32758</SRS>' +
+'      <SRS>EPSG:32759</SRS>' +
+'      <SRS>EPSG:32760</SRS>' +
+'      <SRS>EPSG:32761</SRS>' +
+'      <SRS>EPSG:32766</SRS>' +
+'      <SRS>EPSG:61206405</SRS>' +
+'      <SRS>EPSG:61216405</SRS>' +
+'      <SRS>EPSG:61226405</SRS>' +
+'      <SRS>EPSG:61236405</SRS>' +
+'      <SRS>EPSG:61246405</SRS>' +
+'      <SRS>EPSG:61266405</SRS>' +
+'      <SRS>EPSG:61266413</SRS>' +
+'      <SRS>EPSG:61276405</SRS>' +
+'      <SRS>EPSG:61286405</SRS>' +
+'      <SRS>EPSG:61296405</SRS>' +
+'      <SRS>EPSG:61306405</SRS>' +
+'      <SRS>EPSG:61306413</SRS>' +
+'      <SRS>EPSG:61316405</SRS>' +
+'      <SRS>EPSG:61326405</SRS>' +
+'      <SRS>EPSG:61336405</SRS>' +
+'      <SRS>EPSG:61346405</SRS>' +
+'      <SRS>EPSG:61356405</SRS>' +
+'      <SRS>EPSG:61366405</SRS>' +
+'      <SRS>EPSG:61376405</SRS>' +
+'      <SRS>EPSG:61386405</SRS>' +
+'      <SRS>EPSG:61396405</SRS>' +
+'      <SRS>EPSG:61406405</SRS>' +
+'      <SRS>EPSG:61406413</SRS>' +
+'      <SRS>EPSG:61416405</SRS>' +
+'      <SRS>EPSG:61426405</SRS>' +
+'      <SRS>EPSG:61436405</SRS>' +
+'      <SRS>EPSG:61446405</SRS>' +
+'      <SRS>EPSG:61456405</SRS>' +
+'      <SRS>EPSG:61466405</SRS>' +
+'      <SRS>EPSG:61476405</SRS>' +
+'      <SRS>EPSG:61486405</SRS>' +
+'      <SRS>EPSG:61486413</SRS>' +
+'      <SRS>EPSG:61496405</SRS>' +
+'      <SRS>EPSG:61506405</SRS>' +
+'      <SRS>EPSG:61516405</SRS>' +
+'      <SRS>EPSG:61516413</SRS>' +
+'      <SRS>EPSG:61526405</SRS>' +
+'      <SRS>EPSG:61526413</SRS>' +
+'      <SRS>EPSG:61536405</SRS>' +
+'      <SRS>EPSG:61546405</SRS>' +
+'      <SRS>EPSG:61556405</SRS>' +
+'      <SRS>EPSG:61566405</SRS>' +
+'      <SRS>EPSG:61576405</SRS>' +
+'      <SRS>EPSG:61586405</SRS>' +
+'      <SRS>EPSG:61596405</SRS>' +
+'      <SRS>EPSG:61606405</SRS>' +
+'      <SRS>EPSG:61616405</SRS>' +
+'      <SRS>EPSG:61626405</SRS>' +
+'      <SRS>EPSG:61636405</SRS>' +
+'      <SRS>EPSG:61636413</SRS>' +
+'      <SRS>EPSG:61646405</SRS>' +
+'      <SRS>EPSG:61656405</SRS>' +
+'      <SRS>EPSG:61666405</SRS>' +
+'      <SRS>EPSG:61676405</SRS>' +
+'      <SRS>EPSG:61676413</SRS>' +
+'      <SRS>EPSG:61686405</SRS>' +
+'      <SRS>EPSG:61696405</SRS>' +
+'      <SRS>EPSG:61706405</SRS>' +
+'      <SRS>EPSG:61706413</SRS>' +
+'      <SRS>EPSG:61716405</SRS>' +
+'      <SRS>EPSG:61716413</SRS>' +
+'      <SRS>EPSG:61736405</SRS>' +
+'      <SRS>EPSG:61736413</SRS>' +
+'      <SRS>EPSG:61746405</SRS>' +
+'      <SRS>EPSG:61756405</SRS>' +
+'      <SRS>EPSG:61766405</SRS>' +
+'      <SRS>EPSG:61766413</SRS>' +
+'      <SRS>EPSG:61786405</SRS>' +
+'      <SRS>EPSG:61796405</SRS>' +
+'      <SRS>EPSG:61806405</SRS>' +
+'      <SRS>EPSG:61806413</SRS>' +
+'      <SRS>EPSG:61816405</SRS>' +
+'      <SRS>EPSG:61826405</SRS>' +
+'      <SRS>EPSG:61836405</SRS>' +
+'      <SRS>EPSG:61846405</SRS>' +
+'      <SRS>EPSG:61886405</SRS>' +
+'      <SRS>EPSG:61896405</SRS>' +
+'      <SRS>EPSG:61896413</SRS>' +
+'      <SRS>EPSG:61906405</SRS>' +
+'      <SRS>EPSG:61906413</SRS>' +
+'      <SRS>EPSG:61916405</SRS>' +
+'      <SRS>EPSG:61926405</SRS>' +
+'      <SRS>EPSG:61936405</SRS>' +
+'      <SRS>EPSG:61946405</SRS>' +
+'      <SRS>EPSG:61956405</SRS>' +
+'      <SRS>EPSG:61966405</SRS>' +
+'      <SRS>EPSG:61976405</SRS>' +
+'      <SRS>EPSG:61986405</SRS>' +
+'      <SRS>EPSG:61996405</SRS>' +
+'      <SRS>EPSG:62006405</SRS>' +
+'      <SRS>EPSG:62016405</SRS>' +
+'      <SRS>EPSG:62026405</SRS>' +
+'      <SRS>EPSG:62036405</SRS>' +
+'      <SRS>EPSG:62046405</SRS>' +
+'      <SRS>EPSG:62056405</SRS>' +
+'      <SRS>EPSG:62066405</SRS>' +
+'      <SRS>EPSG:62076405</SRS>' +
+'      <SRS>EPSG:62086405</SRS>' +
+'      <SRS>EPSG:62096405</SRS>' +
+'      <SRS>EPSG:62106405</SRS>' +
+'      <SRS>EPSG:62116405</SRS>' +
+'      <SRS>EPSG:62126405</SRS>' +
+'      <SRS>EPSG:62136405</SRS>' +
+'      <SRS>EPSG:62146405</SRS>' +
+'      <SRS>EPSG:62156405</SRS>' +
+'      <SRS>EPSG:62166405</SRS>' +
+'      <SRS>EPSG:62186405</SRS>' +
+'      <SRS>EPSG:62196405</SRS>' +
+'      <SRS>EPSG:62206405</SRS>' +
+'      <SRS>EPSG:62216405</SRS>' +
+'      <SRS>EPSG:62226405</SRS>' +
+'      <SRS>EPSG:62236405</SRS>' +
+'      <SRS>EPSG:62246405</SRS>' +
+'      <SRS>EPSG:62256405</SRS>' +
+'      <SRS>EPSG:62276405</SRS>' +
+'      <SRS>EPSG:62296405</SRS>' +
+'      <SRS>EPSG:62306405</SRS>' +
+'      <SRS>EPSG:62316405</SRS>' +
+'      <SRS>EPSG:62326405</SRS>' +
+'      <SRS>EPSG:62336405</SRS>' +
+'      <SRS>EPSG:62366405</SRS>' +
+'      <SRS>EPSG:62376405</SRS>' +
+'      <SRS>EPSG:62386405</SRS>' +
+'      <SRS>EPSG:62396405</SRS>' +
+'      <SRS>EPSG:62406405</SRS>' +
+'      <SRS>EPSG:62416405</SRS>' +
+'      <SRS>EPSG:62426405</SRS>' +
+'      <SRS>EPSG:62436405</SRS>' +
+'      <SRS>EPSG:62446405</SRS>' +
+'      <SRS>EPSG:62456405</SRS>' +
+'      <SRS>EPSG:62466405</SRS>' +
+'      <SRS>EPSG:62476405</SRS>' +
+'      <SRS>EPSG:62486405</SRS>' +
+'      <SRS>EPSG:62496405</SRS>' +
+'      <SRS>EPSG:62506405</SRS>' +
+'      <SRS>EPSG:62516405</SRS>' +
+'      <SRS>EPSG:62526405</SRS>' +
+'      <SRS>EPSG:62536405</SRS>' +
+'      <SRS>EPSG:62546405</SRS>' +
+'      <SRS>EPSG:62556405</SRS>' +
+'      <SRS>EPSG:62566405</SRS>' +
+'      <SRS>EPSG:62576405</SRS>' +
+'      <SRS>EPSG:62586405</SRS>' +
+'      <SRS>EPSG:62586413</SRS>' +
+'      <SRS>EPSG:62596405</SRS>' +
+'      <SRS>EPSG:62616405</SRS>' +
+'      <SRS>EPSG:62626405</SRS>' +
+'      <SRS>EPSG:62636405</SRS>' +
+'      <SRS>EPSG:62646405</SRS>' +
+'      <SRS>EPSG:62656405</SRS>' +
+'      <SRS>EPSG:62666405</SRS>' +
+'      <SRS>EPSG:62676405</SRS>' +
+'      <SRS>EPSG:62686405</SRS>' +
+'      <SRS>EPSG:62696405</SRS>' +
+'      <SRS>EPSG:62706405</SRS>' +
+'      <SRS>EPSG:62716405</SRS>' +
+'      <SRS>EPSG:62726405</SRS>' +
+'      <SRS>EPSG:62736405</SRS>' +
+'      <SRS>EPSG:62746405</SRS>' +
+'      <SRS>EPSG:62756405</SRS>' +
+'      <SRS>EPSG:62766405</SRS>' +
+'      <SRS>EPSG:62776405</SRS>' +
+'      <SRS>EPSG:62786405</SRS>' +
+'      <SRS>EPSG:62796405</SRS>' +
+'      <SRS>EPSG:62806405</SRS>' +
+'      <SRS>EPSG:62816405</SRS>' +
+'      <SRS>EPSG:62826405</SRS>' +
+'      <SRS>EPSG:62836405</SRS>' +
+'      <SRS>EPSG:62836413</SRS>' +
+'      <SRS>EPSG:62846405</SRS>' +
+'      <SRS>EPSG:62856405</SRS>' +
+'      <SRS>EPSG:62866405</SRS>' +
+'      <SRS>EPSG:62886405</SRS>' +
+'      <SRS>EPSG:62896405</SRS>' +
+'      <SRS>EPSG:62926405</SRS>' +
+'      <SRS>EPSG:62936405</SRS>' +
+'      <SRS>EPSG:62956405</SRS>' +
+'      <SRS>EPSG:62976405</SRS>' +
+'      <SRS>EPSG:62986405</SRS>' +
+'      <SRS>EPSG:62996405</SRS>' +
+'      <SRS>EPSG:63006405</SRS>' +
+'      <SRS>EPSG:63016405</SRS>' +
+'      <SRS>EPSG:63026405</SRS>' +
+'      <SRS>EPSG:63036405</SRS>' +
+'      <SRS>EPSG:63046405</SRS>' +
+'      <SRS>EPSG:63066405</SRS>' +
+'      <SRS>EPSG:63076405</SRS>' +
+'      <SRS>EPSG:63086405</SRS>' +
+'      <SRS>EPSG:63096405</SRS>' +
+'      <SRS>EPSG:63106405</SRS>' +
+'      <SRS>EPSG:63116405</SRS>' +
+'      <SRS>EPSG:63126405</SRS>' +
+'      <SRS>EPSG:63136405</SRS>' +
+'      <SRS>EPSG:63146405</SRS>' +
+'      <SRS>EPSG:63156405</SRS>' +
+'      <SRS>EPSG:63166405</SRS>' +
+'      <SRS>EPSG:63176405</SRS>' +
+'      <SRS>EPSG:63186405</SRS>' +
+'      <SRS>EPSG:63196405</SRS>' +
+'      <SRS>EPSG:63226405</SRS>' +
+'      <SRS>EPSG:63246405</SRS>' +
+'      <SRS>EPSG:63266405</SRS>' +
+'      <SRS>EPSG:63266406</SRS>' +
+'      <SRS>EPSG:63266407</SRS>' +
+'      <SRS>EPSG:63266408</SRS>' +
+'      <SRS>EPSG:63266409</SRS>' +
+'      <SRS>EPSG:63266410</SRS>' +
+'      <SRS>EPSG:63266411</SRS>' +
+'      <SRS>EPSG:63266412</SRS>' +
+'      <SRS>EPSG:63266413</SRS>' +
+'      <SRS>EPSG:63266414</SRS>' +
+'      <SRS>EPSG:63266415</SRS>' +
+'      <SRS>EPSG:63266416</SRS>' +
+'      <SRS>EPSG:63266417</SRS>' +
+'      <SRS>EPSG:63266418</SRS>' +
+'      <SRS>EPSG:63266419</SRS>' +
+'      <SRS>EPSG:63266420</SRS>' +
+'      <SRS>EPSG:66006405</SRS>' +
+'      <SRS>EPSG:66016405</SRS>' +
+'      <SRS>EPSG:66026405</SRS>' +
+'      <SRS>EPSG:66036405</SRS>' +
+'      <SRS>EPSG:66046405</SRS>' +
+'      <SRS>EPSG:66056405</SRS>' +
+'      <SRS>EPSG:66066405</SRS>' +
+'      <SRS>EPSG:66076405</SRS>' +
+'      <SRS>EPSG:66086405</SRS>' +
+'      <SRS>EPSG:66096405</SRS>' +
+'      <SRS>EPSG:66106405</SRS>' +
+'      <SRS>EPSG:66116405</SRS>' +
+'      <SRS>EPSG:66126405</SRS>' +
+'      <SRS>EPSG:66126413</SRS>' +
+'      <SRS>EPSG:66136405</SRS>' +
+'      <SRS>EPSG:66146405</SRS>' +
+'      <SRS>EPSG:66156405</SRS>' +
+'      <SRS>EPSG:66166405</SRS>' +
+'      <SRS>EPSG:66186405</SRS>' +
+'      <SRS>EPSG:66196405</SRS>' +
+'      <SRS>EPSG:66196413</SRS>' +
+'      <SRS>EPSG:66206405</SRS>' +
+'      <SRS>EPSG:66216405</SRS>' +
+'      <SRS>EPSG:66226405</SRS>' +
+'      <SRS>EPSG:66236405</SRS>' +
+'      <SRS>EPSG:66246405</SRS>' +
+'      <SRS>EPSG:66246413</SRS>' +
+'      <SRS>EPSG:66256405</SRS>' +
+'      <SRS>EPSG:66266405</SRS>' +
+'      <SRS>EPSG:66276405</SRS>' +
+'      <SRS>EPSG:66276413</SRS>' +
+'      <SRS>EPSG:66286405</SRS>' +
+'      <SRS>EPSG:66296405</SRS>' +
+'      <SRS>EPSG:66306405</SRS>' +
+'      <SRS>EPSG:66316405</SRS>' +
+'      <SRS>EPSG:66326405</SRS>' +
+'      <SRS>EPSG:66336405</SRS>' +
+'      <SRS>EPSG:66346405</SRS>' +
+'      <SRS>EPSG:66356405</SRS>' +
+'      <SRS>EPSG:66366405</SRS>' +
+'      <SRS>EPSG:66376405</SRS>' +
+'      <SRS>EPSG:66386405</SRS>' +
+'      <SRS>EPSG:66396405</SRS>' +
+'      <SRS>EPSG:66406405</SRS>' +
+'      <SRS>EPSG:66406413</SRS>' +
+'      <SRS>EPSG:66416405</SRS>' +
+'      <SRS>EPSG:66426405</SRS>' +
+'      <SRS>EPSG:66436405</SRS>' +
+'      <SRS>EPSG:66446405</SRS>' +
+'      <SRS>EPSG:66456405</SRS>' +
+'      <SRS>EPSG:66456413</SRS>' +
+'      <SRS>EPSG:66466405</SRS>' +
+'      <SRS>EPSG:66576405</SRS>' +
+'      <SRS>EPSG:66586405</SRS>' +
+'      <SRS>EPSG:66596405</SRS>' +
+'      <SRS>EPSG:66596413</SRS>' +
+'      <SRS>EPSG:66606405</SRS>' +
+'      <SRS>EPSG:66616405</SRS>' +
+'      <SRS>EPSG:66616413</SRS>' +
+'      <SRS>EPSG:66636405</SRS>' +
+'      <SRS>EPSG:66646405</SRS>' +
+'      <SRS>EPSG:66656405</SRS>' +
+'      <SRS>EPSG:66666405</SRS>' +
+'      <SRS>EPSG:66676405</SRS>' +
+'      <SRS>EPSG:68016405</SRS>' +
+'      <SRS>EPSG:68026405</SRS>' +
+'      <SRS>EPSG:68036405</SRS>' +
+'      <SRS>EPSG:68046405</SRS>' +
+'      <SRS>EPSG:68056405</SRS>' +
+'      <SRS>EPSG:68066405</SRS>' +
+'      <SRS>EPSG:68086405</SRS>' +
+'      <SRS>EPSG:68096405</SRS>' +
+'      <SRS>EPSG:68136405</SRS>' +
+'      <SRS>EPSG:68146405</SRS>' +
+'      <SRS>EPSG:68156405</SRS>' +
+'      <SRS>EPSG:68186405</SRS>' +
+'      <SRS>EPSG:68206405</SRS>' +
+'      <SRS>EPSG:69036405</SRS>' +
+'      <SRS>EPSG:42302</SRS>' +
+'      <SRS>EPSG:42301</SRS>' +
+'      <SRS>EPSG:900913</SRS>' +
+'      <SRS>EPSG:45556</SRS>' +
+'      <SRS>EPSG:45555</SRS>' +
+'      <SRS>EPSG:54004</SRS>' +
+'      <SRS>EPSG:41001</SRS>' +
+'      <SRS>EPSG:42311</SRS>' +
+'      <SRS>EPSG:42310</SRS>' +
+'      <SRS>EPSG:18001</SRS>' +
+'      <SRS>EPSG:100003</SRS>' +
+'      <SRS>EPSG:42106</SRS>' +
+'      <SRS>EPSG:100002</SRS>' +
+'      <SRS>EPSG:42105</SRS>' +
+'      <SRS>EPSG:100001</SRS>' +
+'      <SRS>EPSG:42309</SRS>' +
+'      <SRS>EPSG:42104</SRS>' +
+'      <SRS>EPSG:42308</SRS>' +
+'      <SRS>EPSG:42103</SRS>' +
+'      <SRS>EPSG:42307</SRS>' +
+'      <SRS>EPSG:42102</SRS>' +
+'      <SRS>EPSG:42306</SRS>' +
+'      <SRS>EPSG:42101</SRS>' +
+'      <SRS>EPSG:42305</SRS>' +
+'      <SRS>EPSG:42304</SRS>' +
+'      <SRS>EPSG:42303</SRS>' +
+'      <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>' +
+'      <Layer queryable="1">' +
+'        <Name>og:bugsites</Name>' +
+'        <Title/>' +
+'        <Abstract>Sample data from GRASS, bug sites location, Spearfish, South Dakota, USA</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>spearfish</Keyword>' +
+'          <Keyword>sfBugsites</Keyword>' +
+'          <Keyword>insects</Keyword>' +
+'          <Keyword>bugsites</Keyword>' +
+'          <Keyword>tiger_beetles</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <LatLonBoundingBox minx="-103.8701581843142" miny="44.286540361238224" maxx="-103.63532819794625" maxy="44.52137034760618"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="590232.0" miny="4914096.0" maxx="608471.0" maxy="4920512.0"/>' +
+'        <Style>' +
+'          <Name>capitals</Name>' +
+'          <Title>Capital cities</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:bugsites"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>og:restricted</Name>' +
+'        <Title/>' +
+'        <Abstract>Sample data from GRASS, restricted areas, Spearfish, South Dakota, USA</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>spearfish</Keyword>' +
+'          <Keyword>restricted</Keyword>' +
+'          <Keyword>sfRestricted</Keyword>' +
+'          <Keyword>areas</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <LatLonBoundingBox minx="-104.36424600670885" miny="43.78798270975212" maxx="-103.06226503558304" maxy="45.089963680877936"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="551796.8125" miny="4901896.0" maxx="652788.5625" maxy="4940954.0"/>' +
+'        <Style>' +
+'          <Name>restricted</Name>' +
+'          <Title>Red, translucent style</Title>' +
+'          <Abstract>A sample style that just prints out a transparent red interior with a red outline</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:restricted"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>og:archsites</Name>' +
+'        <Title/>' +
+'        <Abstract>Sample data from GRASS, archeological sites location, Spearfish, South Dakota, USA</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>archsites</Keyword>' +
+'          <Keyword>spearfish</Keyword>' +
+'          <Keyword>sfArchsites</Keyword>' +
+'          <Keyword>archeology</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <LatLonBoundingBox minx="-103.87480459767542" miny="44.31295793136913" maxx="-103.63549073047534" maxy="44.55227179856921"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="589860.0" miny="4914479.0" maxx="608355.0" maxy="4926490.0"/>' +
+'        <Style>' +
+'          <Name>point</Name>' +
+'          <Title>Default point</Title>' +
+'          <Abstract>A sample style that just prints out a 6px wide red square</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:archsites"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>og:streams</Name>' +
+'        <Title/>' +
+'        <Abstract>Sample data from GRASS, streams, Spearfish, South Dakota, USA</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>spearfish</Keyword>' +
+'          <Keyword>sfStreams</Keyword>' +
+'          <Keyword>streams</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <LatLonBoundingBox minx="-103.88033574142051" miny="44.30711172484593" maxx="-103.62022283326024" maxy="44.5672246330062"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="589443.0" miny="4913935.0" maxx="609526.75" maxy="4928059.5"/>' +
+'        <Style>' +
+'          <Name>simple_streams</Name>' +
+'          <Title>Default Styler for streams segments</Title>' +
+'          <Abstract>Blue lines, 2px wide</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:streams"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tiger:poly_landmarks</Name>' +
+'        <Title>Manhattan (NY) landmarks</Title>' +
+'        <Abstract>Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>DS_poly_landmarks</Keyword>' +
+'          <Keyword>landmarks</Keyword>' +
+'          <Keyword>manhattan</Keyword>' +
+'          <Keyword>poly_landmarks</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-74.0828672737" miny="40.67246384130001" maxx="-73.8660689563" maxy="40.8892621587"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.90782" maxy="40.882078"/>' +
+'        <Style>' +
+'          <Name>poly_landmarks</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poly_landmarks"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tiger:poi</Name>' +
+'        <Title>Manhattan (NY) points of interest</Title>' +
+'        <Abstract>Points of interest in New York, New York (on Manhattan). One of the attributes contains the name of a file with a picture of the point of interest.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>poi</Keyword>' +
+'          <Keyword>Manhattan</Keyword>' +
+'          <Keyword>DS_poi</Keyword>' +
+'          <Keyword>points_of_interest</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-74.01244590356289" miny="40.70750285086222" maxx="-74.00795911725866" maxy="40.711989637166425"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-74.0118315772888" miny="40.70754683896324" maxx="-74.00153046439813" maxy="40.719885123828675"/>' +
+'        <Style>' +
+'          <Name>poi</Name>' +
+'          <Title>Points of interest</Title>' +
+'          <Abstract>Manhattan points of interest</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poi"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tiger:tiger_roads</Name>' +
+'        <Title>Manhattan (NY) roads</Title>' +
+'        <Abstract>Highly simplified road layout of Manhattan in New York..</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>DS_tiger_roads</Keyword>' +
+'          <Keyword>tiger_roads</Keyword>' +
+'          <Keyword>roads</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-74.06603057" miny="40.68228143" maxx="-73.86819443" maxy="40.880117569999996"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-74.02722" miny="40.684221" maxx="-73.907005" maxy="40.878178"/>' +
+'        <Style>' +
+'          <Name>tiger_roads</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:tiger_roads"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>za:za_natural</Name>' +
+'        <Title>Natural Landmarks in South Africa</Title>' +
+'        <Abstract>This layer describes natural features of South Africa such as forests and lakes.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>water</Keyword>' +
+'          <Keyword>forests</Keyword>' +
+'          <Keyword>landmarks</Keyword>' +
+'          <Keyword>Africa</Keyword>' +
+'          <Keyword>South</Keyword>' +
+'          <Keyword>natural</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="16.779241142272962" miny="-36.53577846527099" maxx="32.70336002349853" maxy="-20.611659584045416"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="16.935359954834" miny="-34.3737831115723" maxx="32.5472412109375" maxy="-22.7736549377441"/>' +
+'        <Style>' +
+'          <Name>za_natural</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_natural"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>za:za_points</Name>' +
+'        <Title>Points of Interest in South Africa</Title>' +
+'        <Abstract>Noteworthy locations such as hotels and tourist attractions in South Africa.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>of</Keyword>' +
+'          <Keyword>tourist</Keyword>' +
+'          <Keyword>landmarks</Keyword>' +
+'          <Keyword>zoo</Keyword>' +
+'          <Keyword>cities</Keyword>' +
+'          <Keyword>interest</Keyword>' +
+'          <Keyword>attractions</Keyword>' +
+'          <Keyword>points</Keyword>' +
+'          <Keyword>hotel</Keyword>' +
+'          <Keyword>museum</Keyword>' +
+'          <Keyword>picnic</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="14.629095230102537" miny="-47.151258316040014" maxx="39.792314376831065" maxy="-21.988039169311488"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="16.4827766418457" miny="-46.9045600891113" maxx="37.9386329650879" maxy="-22.2347373962402"/>' +
+'        <Style>' +
+'          <Name>za_points</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_points"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>za:za_roads</Name>' +
+'        <Title>South African Roads</Title>' +
+'        <Abstract>This layer describes roads in South Africa.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>south</Keyword>' +
+'          <Keyword>africa</Keyword>' +
+'          <Keyword>roads</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="16.29388177871706" miny="-36.85438787460323" maxx="33.04232465744013" maxy="-20.10594499588016"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="16.4580821990967" miny="-34.8331336975098" maxx="32.8781242370605" maxy="-22.1271991729736"/>' +
+'        <Style>' +
+'          <Name>za_roads</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_roads"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>za:za_vegetation</Name>' +
+'        <Title>South African Vegetation</Title>' +
+'        <Abstract>This layer describes vegetated areas in South Africa, categorized by biome.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>south</Keyword>' +
+'          <Keyword>vegetation</Keyword>' +
+'          <Keyword>africa</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="16.30492322921758" miny="-36.855452365875216" maxx="33.05824930191042" maxy="-20.102126293182376"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="16.4691715240479" miny="-34.8336486816406" maxx="32.8940010070801" maxy="-22.123929977417"/>' +
+'        <Style>' +
+'          <Name>za_vegetation</Name>' +
+'          <Title>Default Styler</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_vegetation"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:tasmania_cities</Name>' +
+'        <Title>Tasmania cities</Title>' +
+'        <Abstract>Cities in Tasmania (actually, just the capital)</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>cities</Keyword>' +
+'          <Keyword>Tasmania</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="145.1667856" miny="-43.706631400000006" maxx="148.30373440000002" maxy="-40.56968259999999"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="147.2910004483" miny="-42.851001816890005" maxx="147.2910004483" maxy="-42.851001816890005"/>' +
+'        <Style>' +
+'          <Name>capitals</Name>' +
+'          <Title>Capital cities</Title>' +
+'          <Abstract/>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_cities"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:tasmania_roads</Name>' +
+'        <Title>Tasmania roads</Title>' +
+'        <Abstract>Main Tasmania roads</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>Roads</Keyword>' +
+'          <Keyword>Tasmania</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="145.1667856" miny="-43.706631400000006" maxx="148.30373440000002" maxy="-40.56968259999999"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="145.19754" miny="-43.423512" maxx="148.27298000000002" maxy="-40.852802"/>' +
+'        <Style>' +
+'          <Name>simple_roads</Name>' +
+'          <Title>Default Styler for simple road segments</Title>' +
+'          <Abstract>Light red line, 2px wide</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_roads"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:tasmania_state_boundaries</Name>' +
+'        <Title>Tasmania state boundaries</Title>' +
+'        <Abstract>Tasmania state boundaries</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>boundaries</Keyword>' +
+'          <Keyword>tasmania_state_boundaries</Keyword>' +
+'          <Keyword>Tasmania</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="143.74100879660003" miny="-44.026947203400006" maxx="148.57295620340003" maxy="-39.194999796599994"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>' +
+'        <Style>' +
+'          <Name>green</Name>' +
+'          <Title>Green polygon</Title>' +
+'          <Abstract>Green fill with black outline</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_state_boundaries"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:tasmania_water_bodies</Name>' +
+'        <Title>Tasmania water bodies</Title>' +
+'        <Abstract>Tasmania water bodies</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>Lakes</Keyword>' +
+'          <Keyword>Bodies</Keyword>' +
+'          <Keyword>Australia</Keyword>' +
+'          <Keyword>Water</Keyword>' +
+'          <Keyword>Tasmania</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="145.95490063999998" miny="-43.04450786" maxx="147.23641436" maxy="-41.762994139999996"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="145.97161899999998" miny="-43.031944" maxx="147.219696" maxy="-41.775558"/>' +
+'        <Style>' +
+'          <Name>cite_lakes</Name>' +
+'          <Title>Blue lake</Title>' +
+'          <Abstract>A blue fill, solid black outline style</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_water_bodies"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:states</Name>' +
+'        <Title>USA Population</Title>' +
+'        <Abstract>This is some census data on the states.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>census</Keyword>' +
+'          <Keyword>united</Keyword>' +
+'          <Keyword>boundaries</Keyword>' +
+'          <Keyword>state</Keyword>' +
+'          <Keyword>states</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-125.30903773" miny="7.705448770000002" maxx="-66.39223326999999" maxy="66.62225323"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-124.73142200000001" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>' +
+'        <Style>' +
+'          <Name>population</Name>' +
+'          <Title>Population in the United States</Title>' +
+'          <Abstract>A sample filter that filters the United States into three' +
+'        categories of population, drawn in different colors</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:states"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tike:waterways</Name>' +
+'        <Title>Waterways</Title>' +
+'        <Abstract>Waterways in Finland.</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>Finland</Keyword>' +
+'          <Keyword>waterways</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="19.530168895721403" miny="58.860618000030506" maxx="31.6566005897522" maxy="70.9870496940613"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="19.649055480957" miny="59.9357719421387" maxx="31.5377140045166" maxy="69.9118957519531"/>' +
+'        <Style>' +
+'          <Name>line</Name>' +
+'          <Title>1 px blue line</Title>' +
+'          <Abstract>Default line style, 1 pixel wide blue</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:waterways"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tike:railways</Name>' +
+'        <Title>roads_Type</Title>' +
+'        <Abstract>Generated from tike</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>tike</Keyword>' +
+'          <Keyword>roads</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="19.5393085479736" miny="-2277.78344726562" maxx="2.971959E7" maxy="4927039.0"/>' +
+'        <Style>' +
+'          <Name>line</Name>' +
+'          <Title>1 px blue line</Title>' +
+'          <Abstract>Default line style, 1 pixel wide blue</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:railways"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tike:roads</Name>' +
+'        <Title>roads_Type</Title>' +
+'        <Abstract>Generated from tike</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>tike</Keyword>' +
+'          <Keyword>roads</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="19.5393085479736" miny="-2277.78344726562" maxx="2.971959E7" maxy="4927039.0"/>' +
+'        <Style>' +
+'          <Name>line</Name>' +
+'          <Title>1 px blue line</Title>' +
+'          <Abstract>Default line style, 1 pixel wide blue</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:roads"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>og:roads</Name>' +
+'        <Title>roads_Type</Title>' +
+'        <Abstract>Generated from sf_reset</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>roads</Keyword>' +
+'          <Keyword>sf_reset</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <LatLonBoundingBox minx="-103.88042792817339" miny="44.308776913708805" maxx="-103.62014761945467" maxy="44.56905722242751"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="589434.8125" miny="4914006.0" maxx="609527.25" maxy="4928377.0"/>' +
+'        <Style>' +
+'          <Name>simple_roads</Name>' +
+'          <Title>Default Styler for simple road segments</Title>' +
+'          <Abstract>Light red line, 2px wide</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:roads"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>tike:points</Name>' +
+'        <Title>roads_Type</Title>' +
+'        <Abstract>Generated from tike</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>tike</Keyword>' +
+'          <Keyword>roads</Keyword>' +
+'        </KeywordList>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <LatLonBoundingBox minx="19.73377216339108" miny="59.107116584777835" maxx="31.40053188323972" maxy="70.77387630462647"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="19.8481521606445" miny="59.8213005065918" maxx="31.2861518859863" maxy="70.0596923828125"/>' +
+'        <Style>' +
+'          <Name>line</Name>' +
+'          <Title>1 px blue line</Title>' +
+'          <Abstract>Default line style, 1 pixel wide blue</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:points"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>topp:bluemarble</Name>' +
+'        <Title>Blue Marble Imagery</Title>' +
+'        <Abstract>Blue Marble NG global bathymetry and topography data from NASA.  More information about the Blue Marble NG project is available from http://earthobservatory.nasa.gov/Features/BlueMarble .</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>WCS</Keyword>' +
+'          <Keyword>bluemarble</Keyword>' +
+'          <Keyword>bluemarble</Keyword>' +
+'        </KeywordList>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <LatLonBoundingBox minx="-180.00000003333" miny="-89.99999996486703" maxx="179.99999993067" maxy="90.000000033333"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-180.00000003333" miny="-89.99999996486703" maxx="179.99999993067" maxy="90.000000033333"/>' +
+'        <Style>' +
+'          <Name>raster</Name>' +
+'          <Title>Raster</Title>' +
+'          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:bluemarble"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>nurc:Arc_Sample</Name>' +
+'        <Title>Global annual rainfall</Title>' +
+'        <Abstract>Global annual rainfall in ArcGrid format</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>WCS</Keyword>' +
+'          <Keyword>arcGridSample</Keyword>' +
+'          <Keyword>arcGridSample_Coverage</Keyword>' +
+'        </KeywordList>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <LatLonBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>' +
+'        <Style>' +
+'          <Name>raster</Name>' +
+'          <Title>Raster</Title>' +
+'          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Arc_Sample"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>nurc:Img_Sample</Name>' +
+'        <Title>North America sample imagery</Title>' +
+'        <Abstract>A very rough imagery of North America</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>WCS</Keyword>' +
+'          <Keyword>worldImageSample</Keyword>' +
+'          <Keyword>worldImageSample_Coverage</Keyword>' +
+'        </KeywordList>' +
+'        <!--WKT definition of this CRS:' +
+'GEOGCS["WGS 84", ' +
+'  DATUM["World Geodetic System 1984", ' +
+'    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], ' +
+'    AUTHORITY["EPSG","6326"]], ' +
+'  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'  UNIT["degree", 0.017453292519943295], ' +
+'  AXIS["Geodetic longitude", EAST], ' +
+'  AXIS["Geodetic latitude", NORTH], ' +
+'  AUTHORITY["EPSG","4326"]]-->' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <LatLonBoundingBox minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>' +
+'        <Style>' +
+'          <Name>raster</Name>' +
+'          <Title>Raster</Title>' +
+'          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Img_Sample"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="1">' +
+'        <Name>sf:sfdem</Name>' +
+'        <Title>Spearfish DEM</Title>' +
+'        <Abstract>Digital Elevation Model data for Spearfish, South Dakota</Abstract>' +
+'        <KeywordList>' +
+'          <Keyword>WCS</Keyword>' +
+'          <Keyword>sf</Keyword>' +
+'          <Keyword>dem</Keyword>' +
+'          <Keyword>digital</Keyword>' +
+'          <Keyword>elevation</Keyword>' +
+'          <Keyword>model</Keyword>' +
+'        </KeywordList>' +
+'        <!--WKT definition of this CRS:' +
+'PROJCS["NAD27 / UTM zone 13N", ' +
+'  GEOGCS["NAD27", ' +
+'    DATUM["North American Datum 1927", ' +
+'      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], ' +
+'      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], ' +
+'      AUTHORITY["EPSG","6267"]], ' +
+'    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], ' +
+'    UNIT["degree", 0.017453292519943295], ' +
+'    AXIS["Geodetic longitude", EAST], ' +
+'    AXIS["Geodetic latitude", NORTH], ' +
+'    AUTHORITY["EPSG","4267"]], ' +
+'  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], ' +
+'  PARAMETER["central_meridian", -105.0], ' +
+'  PARAMETER["latitude_of_origin", 0.0], ' +
+'  PARAMETER["scale_factor", 0.9996], ' +
+'  PARAMETER["false_easting", 500000.0], ' +
+'  PARAMETER["false_northing", 0.0], ' +
+'  UNIT["m", 1.0], ' +
+'  AXIS["Easting", EAST], ' +
+'  AXIS["Northing", NORTH], ' +
+'  AUTHORITY["EPSG","26713"]]-->' +
+'        <SRS>EPSG:26713</SRS>' +
+'        <LatLonBoundingBox minx="-103.87108701853181" miny="44.370187074132616" maxx="-103.62940739432703" maxy="44.5016011535299"/>' +
+'        <BoundingBox SRS="EPSG:26713" minx="589980.0" miny="4913700.0" maxx="609000.0" maxy="4928010.0"/>' +
+'        <Style>' +
+'          <Name>dem</Name>' +
+'          <Title>Simple DEM style</Title>' +
+'          <Abstract>Classic elevation color progression</Abstract>' +
+'          <LegendURL width="20" height="20">' +
+'            <Format>image/png</Format>' +
+'            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:sfdem"/>' +
+'          </LegendURL>' +
+'        </Style>' +
+'      </Layer>' +
+'      <Layer queryable="0">' +
+'        <Name>tasmania</Name>' +
+'        <Title>tasmania</Title>' +
+'        <Abstract>Layer-Group type layer: tasmania</Abstract>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <LatLonBoundingBox minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>' +
+'      </Layer>' +
+'      <Layer queryable="0">' +
+'        <Name>tiger-ny</Name>' +
+'        <Title>tiger-ny</Title>' +
+'        <Abstract>Layer-Group type layer: tiger-ny</Abstract>' +
+'        <SRS>EPSG:4326</SRS>' +
+'        <LatLonBoundingBox minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>' +
+'        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>' +
+'      </Layer>' +
+'    </Layer>' +
+'  </Capability>' +
+'</WMT_MS_Capabilities>';
+

Copied: sandbox/ahocevar/playground/tests/speed/wmscaps.xml (from rev 10919, trunk/openlayers/tests/speed/wmscaps.xml)
===================================================================
--- sandbox/ahocevar/playground/tests/speed/wmscaps.xml	                        (rev 0)
+++ sandbox/ahocevar/playground/tests/speed/wmscaps.xml	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,4954 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE WMT_MS_Capabilities SYSTEM "http://demo.opengeo.org/geoserver/schemas/wms/1.1.1/WMS_MS_Capabilities.dtd">
+<WMT_MS_Capabilities version="1.1.1" updateSequence="145">
+  <Service>
+    <Name>OGC:WMS</Name>
+    <Title>GeoServer Web Map Service</Title>
+    <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
+    <KeywordList>
+      <Keyword>WFS</Keyword>
+      <Keyword>WMS</Keyword>
+      <Keyword>GEOSERVER</Keyword>
+    </KeywordList>
+    <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms"/>
+    <ContactInformation>
+      <ContactPersonPrimary>
+        <ContactPerson>Claudius Ptolomaeus</ContactPerson>
+        <ContactOrganization>The ancient geographes INC</ContactOrganization>
+      </ContactPersonPrimary>
+      <ContactPosition>Chief geographer</ContactPosition>
+      <ContactAddress>
+        <AddressType>Work</AddressType>
+        <Address/>
+        <City>Alexandria</City>
+        <StateOrProvince/>
+        <PostCode/>
+        <Country>Egypt</Country>
+      </ContactAddress>
+      <ContactVoiceTelephone/>
+      <ContactFacsimileTelephone/>
+      <ContactElectronicMailAddress>claudius.ptolomaeus at gmail.com</ContactElectronicMailAddress>
+    </ContactInformation>
+    <Fees>NONE</Fees>
+    <AccessConstraints>NONE</AccessConstraints>
+  </Service>
+  <Capability>
+    <Request>
+      <GetCapabilities>
+        <Format>application/vnd.ogc.wms_xml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+            <Post>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Post>
+          </HTTP>
+        </DCPType>
+      </GetCapabilities>
+      <GetMap>
+        <Format>image/png</Format>
+        <Format>application/atom xml</Format>
+        <Format>application/atom+xml</Format>
+        <Format>application/openlayers</Format>
+        <Format>application/pdf</Format>
+        <Format>application/rss xml</Format>
+        <Format>application/rss+xml</Format>
+        <Format>application/vnd.google-earth.kml</Format>
+        <Format>application/vnd.google-earth.kml xml</Format>
+        <Format>application/vnd.google-earth.kml+xml</Format>
+        <Format>application/vnd.google-earth.kmz</Format>
+        <Format>application/vnd.google-earth.kmz xml</Format>
+        <Format>application/vnd.google-earth.kmz+xml</Format>
+        <Format>atom</Format>
+        <Format>image/geotiff</Format>
+        <Format>image/geotiff8</Format>
+        <Format>image/gif</Format>
+        <Format>image/jpeg</Format>
+        <Format>image/png8</Format>
+        <Format>image/svg</Format>
+        <Format>image/svg xml</Format>
+        <Format>image/svg+xml</Format>
+        <Format>image/tiff</Format>
+        <Format>image/tiff8</Format>
+        <Format>kml</Format>
+        <Format>kmz</Format>
+        <Format>openlayers</Format>
+        <Format>rss</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </GetMap>
+      <GetFeatureInfo>
+        <Format>text/plain</Format>
+        <Format>text/html</Format>
+        <Format>application/vnd.ogc.gml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+            <Post>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Post>
+          </HTTP>
+        </DCPType>
+      </GetFeatureInfo>
+      <DescribeLayer>
+        <Format>application/vnd.ogc.wms_xml</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </DescribeLayer>
+      <GetLegendGraphic>
+        <Format>image/png</Format>
+        <Format>image/jpeg</Format>
+        <Format>image/gif</Format>
+        <DCPType>
+          <HTTP>
+            <Get>
+              <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms?SERVICE=WMS&amp;"/>
+            </Get>
+          </HTTP>
+        </DCPType>
+      </GetLegendGraphic>
+    </Request>
+    <Exception>
+      <Format>application/vnd.ogc.se_xml</Format>
+    </Exception>
+    <UserDefinedSymbolization SupportSLD="1" UserLayer="1" UserStyle="1" RemoteWFS="1"/>
+    <Layer>
+      <Title>GeoServer Web Map Service</Title>
+      <Abstract>A compliant implementation of WMS 1.1.1 plus most of the SLD 1.0 extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
+      <!--All supported EPSG projections:-->
+      <SRS>EPSG:WGS84(DD)</SRS>
+      <SRS>EPSG:2000</SRS>
+      <SRS>EPSG:2001</SRS>
+      <SRS>EPSG:2002</SRS>
+      <SRS>EPSG:2003</SRS>
+      <SRS>EPSG:2004</SRS>
+      <SRS>EPSG:2005</SRS>
+      <SRS>EPSG:2006</SRS>
+      <SRS>EPSG:2007</SRS>
+      <SRS>EPSG:2008</SRS>
+      <SRS>EPSG:2009</SRS>
+      <SRS>EPSG:2010</SRS>
+      <SRS>EPSG:2011</SRS>
+      <SRS>EPSG:2012</SRS>
+      <SRS>EPSG:2013</SRS>
+      <SRS>EPSG:2014</SRS>
+      <SRS>EPSG:2015</SRS>
+      <SRS>EPSG:2016</SRS>
+      <SRS>EPSG:2017</SRS>
+      <SRS>EPSG:2018</SRS>
+      <SRS>EPSG:2019</SRS>
+      <SRS>EPSG:2020</SRS>
+      <SRS>EPSG:2021</SRS>
+      <SRS>EPSG:2022</SRS>
+      <SRS>EPSG:2023</SRS>
+      <SRS>EPSG:2024</SRS>
+      <SRS>EPSG:2025</SRS>
+      <SRS>EPSG:2026</SRS>
+      <SRS>EPSG:2027</SRS>
+      <SRS>EPSG:2028</SRS>
+      <SRS>EPSG:2029</SRS>
+      <SRS>EPSG:2030</SRS>
+      <SRS>EPSG:2031</SRS>
+      <SRS>EPSG:2032</SRS>
+      <SRS>EPSG:2033</SRS>
+      <SRS>EPSG:2034</SRS>
+      <SRS>EPSG:2035</SRS>
+      <SRS>EPSG:2036</SRS>
+      <SRS>EPSG:2037</SRS>
+      <SRS>EPSG:2038</SRS>
+      <SRS>EPSG:2039</SRS>
+      <SRS>EPSG:2040</SRS>
+      <SRS>EPSG:2041</SRS>
+      <SRS>EPSG:2042</SRS>
+      <SRS>EPSG:2043</SRS>
+      <SRS>EPSG:2044</SRS>
+      <SRS>EPSG:2045</SRS>
+      <SRS>EPSG:2046</SRS>
+      <SRS>EPSG:2047</SRS>
+      <SRS>EPSG:2048</SRS>
+      <SRS>EPSG:2049</SRS>
+      <SRS>EPSG:2050</SRS>
+      <SRS>EPSG:2051</SRS>
+      <SRS>EPSG:2052</SRS>
+      <SRS>EPSG:2053</SRS>
+      <SRS>EPSG:2054</SRS>
+      <SRS>EPSG:2055</SRS>
+      <SRS>EPSG:2056</SRS>
+      <SRS>EPSG:2057</SRS>
+      <SRS>EPSG:2058</SRS>
+      <SRS>EPSG:2059</SRS>
+      <SRS>EPSG:2060</SRS>
+      <SRS>EPSG:2061</SRS>
+      <SRS>EPSG:2062</SRS>
+      <SRS>EPSG:2063</SRS>
+      <SRS>EPSG:2064</SRS>
+      <SRS>EPSG:2065</SRS>
+      <SRS>EPSG:2066</SRS>
+      <SRS>EPSG:2067</SRS>
+      <SRS>EPSG:2068</SRS>
+      <SRS>EPSG:2069</SRS>
+      <SRS>EPSG:2070</SRS>
+      <SRS>EPSG:2071</SRS>
+      <SRS>EPSG:2072</SRS>
+      <SRS>EPSG:2073</SRS>
+      <SRS>EPSG:2074</SRS>
+      <SRS>EPSG:2075</SRS>
+      <SRS>EPSG:2076</SRS>
+      <SRS>EPSG:2077</SRS>
+      <SRS>EPSG:2078</SRS>
+      <SRS>EPSG:2079</SRS>
+      <SRS>EPSG:2080</SRS>
+      <SRS>EPSG:2081</SRS>
+      <SRS>EPSG:2082</SRS>
+      <SRS>EPSG:2083</SRS>
+      <SRS>EPSG:2084</SRS>
+      <SRS>EPSG:2085</SRS>
+      <SRS>EPSG:2086</SRS>
+      <SRS>EPSG:2087</SRS>
+      <SRS>EPSG:2088</SRS>
+      <SRS>EPSG:2089</SRS>
+      <SRS>EPSG:2090</SRS>
+      <SRS>EPSG:2091</SRS>
+      <SRS>EPSG:2092</SRS>
+      <SRS>EPSG:2093</SRS>
+      <SRS>EPSG:2094</SRS>
+      <SRS>EPSG:2095</SRS>
+      <SRS>EPSG:2096</SRS>
+      <SRS>EPSG:2097</SRS>
+      <SRS>EPSG:2098</SRS>
+      <SRS>EPSG:2099</SRS>
+      <SRS>EPSG:2100</SRS>
+      <SRS>EPSG:2101</SRS>
+      <SRS>EPSG:2102</SRS>
+      <SRS>EPSG:2103</SRS>
+      <SRS>EPSG:2104</SRS>
+      <SRS>EPSG:2105</SRS>
+      <SRS>EPSG:2106</SRS>
+      <SRS>EPSG:2107</SRS>
+      <SRS>EPSG:2108</SRS>
+      <SRS>EPSG:2109</SRS>
+      <SRS>EPSG:2110</SRS>
+      <SRS>EPSG:2111</SRS>
+      <SRS>EPSG:2112</SRS>
+      <SRS>EPSG:2113</SRS>
+      <SRS>EPSG:2114</SRS>
+      <SRS>EPSG:2115</SRS>
+      <SRS>EPSG:2116</SRS>
+      <SRS>EPSG:2117</SRS>
+      <SRS>EPSG:2118</SRS>
+      <SRS>EPSG:2119</SRS>
+      <SRS>EPSG:2120</SRS>
+      <SRS>EPSG:2121</SRS>
+      <SRS>EPSG:2122</SRS>
+      <SRS>EPSG:2123</SRS>
+      <SRS>EPSG:2124</SRS>
+      <SRS>EPSG:2125</SRS>
+      <SRS>EPSG:2126</SRS>
+      <SRS>EPSG:2127</SRS>
+      <SRS>EPSG:2128</SRS>
+      <SRS>EPSG:2129</SRS>
+      <SRS>EPSG:2130</SRS>
+      <SRS>EPSG:2131</SRS>
+      <SRS>EPSG:2132</SRS>
+      <SRS>EPSG:2133</SRS>
+      <SRS>EPSG:2134</SRS>
+      <SRS>EPSG:2135</SRS>
+      <SRS>EPSG:2136</SRS>
+      <SRS>EPSG:2137</SRS>
+      <SRS>EPSG:2138</SRS>
+      <SRS>EPSG:2139</SRS>
+      <SRS>EPSG:2140</SRS>
+      <SRS>EPSG:2141</SRS>
+      <SRS>EPSG:2142</SRS>
+      <SRS>EPSG:2143</SRS>
+      <SRS>EPSG:2144</SRS>
+      <SRS>EPSG:2145</SRS>
+      <SRS>EPSG:2146</SRS>
+      <SRS>EPSG:2147</SRS>
+      <SRS>EPSG:2148</SRS>
+      <SRS>EPSG:2149</SRS>
+      <SRS>EPSG:2150</SRS>
+      <SRS>EPSG:2151</SRS>
+      <SRS>EPSG:2152</SRS>
+      <SRS>EPSG:2153</SRS>
+      <SRS>EPSG:2154</SRS>
+      <SRS>EPSG:2155</SRS>
+      <SRS>EPSG:2156</SRS>
+      <SRS>EPSG:2157</SRS>
+      <SRS>EPSG:2158</SRS>
+      <SRS>EPSG:2159</SRS>
+      <SRS>EPSG:2160</SRS>
+      <SRS>EPSG:2161</SRS>
+      <SRS>EPSG:2162</SRS>
+      <SRS>EPSG:2163</SRS>
+      <SRS>EPSG:2164</SRS>
+      <SRS>EPSG:2165</SRS>
+      <SRS>EPSG:2166</SRS>
+      <SRS>EPSG:2167</SRS>
+      <SRS>EPSG:2168</SRS>
+      <SRS>EPSG:2169</SRS>
+      <SRS>EPSG:2170</SRS>
+      <SRS>EPSG:2171</SRS>
+      <SRS>EPSG:2172</SRS>
+      <SRS>EPSG:2173</SRS>
+      <SRS>EPSG:2174</SRS>
+      <SRS>EPSG:2175</SRS>
+      <SRS>EPSG:2176</SRS>
+      <SRS>EPSG:2177</SRS>
+      <SRS>EPSG:2178</SRS>
+      <SRS>EPSG:2179</SRS>
+      <SRS>EPSG:2180</SRS>
+      <SRS>EPSG:2188</SRS>
+      <SRS>EPSG:2189</SRS>
+      <SRS>EPSG:2190</SRS>
+      <SRS>EPSG:2191</SRS>
+      <SRS>EPSG:2192</SRS>
+      <SRS>EPSG:2193</SRS>
+      <SRS>EPSG:2194</SRS>
+      <SRS>EPSG:2195</SRS>
+      <SRS>EPSG:2196</SRS>
+      <SRS>EPSG:2197</SRS>
+      <SRS>EPSG:2198</SRS>
+      <SRS>EPSG:2199</SRS>
+      <SRS>EPSG:2200</SRS>
+      <SRS>EPSG:2201</SRS>
+      <SRS>EPSG:2202</SRS>
+      <SRS>EPSG:2203</SRS>
+      <SRS>EPSG:2204</SRS>
+      <SRS>EPSG:2205</SRS>
+      <SRS>EPSG:2206</SRS>
+      <SRS>EPSG:2207</SRS>
+      <SRS>EPSG:2208</SRS>
+      <SRS>EPSG:2209</SRS>
+      <SRS>EPSG:2210</SRS>
+      <SRS>EPSG:2211</SRS>
+      <SRS>EPSG:2212</SRS>
+      <SRS>EPSG:2213</SRS>
+      <SRS>EPSG:2214</SRS>
+      <SRS>EPSG:2215</SRS>
+      <SRS>EPSG:2216</SRS>
+      <SRS>EPSG:2217</SRS>
+      <SRS>EPSG:2218</SRS>
+      <SRS>EPSG:2219</SRS>
+      <SRS>EPSG:2220</SRS>
+      <SRS>EPSG:2221</SRS>
+      <SRS>EPSG:2222</SRS>
+      <SRS>EPSG:2223</SRS>
+      <SRS>EPSG:2224</SRS>
+      <SRS>EPSG:2225</SRS>
+      <SRS>EPSG:2226</SRS>
+      <SRS>EPSG:2227</SRS>
+      <SRS>EPSG:2228</SRS>
+      <SRS>EPSG:2229</SRS>
+      <SRS>EPSG:2230</SRS>
+      <SRS>EPSG:2231</SRS>
+      <SRS>EPSG:2232</SRS>
+      <SRS>EPSG:2233</SRS>
+      <SRS>EPSG:2234</SRS>
+      <SRS>EPSG:2235</SRS>
+      <SRS>EPSG:2236</SRS>
+      <SRS>EPSG:2237</SRS>
+      <SRS>EPSG:2238</SRS>
+      <SRS>EPSG:2239</SRS>
+      <SRS>EPSG:2240</SRS>
+      <SRS>EPSG:2241</SRS>
+      <SRS>EPSG:2242</SRS>
+      <SRS>EPSG:2243</SRS>
+      <SRS>EPSG:2244</SRS>
+      <SRS>EPSG:2245</SRS>
+      <SRS>EPSG:2246</SRS>
+      <SRS>EPSG:2247</SRS>
+      <SRS>EPSG:2248</SRS>
+      <SRS>EPSG:2249</SRS>
+      <SRS>EPSG:2250</SRS>
+      <SRS>EPSG:2251</SRS>
+      <SRS>EPSG:2252</SRS>
+      <SRS>EPSG:2253</SRS>
+      <SRS>EPSG:2254</SRS>
+      <SRS>EPSG:2255</SRS>
+      <SRS>EPSG:2256</SRS>
+      <SRS>EPSG:2257</SRS>
+      <SRS>EPSG:2258</SRS>
+      <SRS>EPSG:2259</SRS>
+      <SRS>EPSG:2260</SRS>
+      <SRS>EPSG:2261</SRS>
+      <SRS>EPSG:2262</SRS>
+      <SRS>EPSG:2263</SRS>
+      <SRS>EPSG:2264</SRS>
+      <SRS>EPSG:2265</SRS>
+      <SRS>EPSG:2266</SRS>
+      <SRS>EPSG:2267</SRS>
+      <SRS>EPSG:2268</SRS>
+      <SRS>EPSG:2269</SRS>
+      <SRS>EPSG:2270</SRS>
+      <SRS>EPSG:2271</SRS>
+      <SRS>EPSG:2272</SRS>
+      <SRS>EPSG:2273</SRS>
+      <SRS>EPSG:2274</SRS>
+      <SRS>EPSG:2275</SRS>
+      <SRS>EPSG:2276</SRS>
+      <SRS>EPSG:2277</SRS>
+      <SRS>EPSG:2278</SRS>
+      <SRS>EPSG:2279</SRS>
+      <SRS>EPSG:2280</SRS>
+      <SRS>EPSG:2281</SRS>
+      <SRS>EPSG:2282</SRS>
+      <SRS>EPSG:2283</SRS>
+      <SRS>EPSG:2284</SRS>
+      <SRS>EPSG:2285</SRS>
+      <SRS>EPSG:2286</SRS>
+      <SRS>EPSG:2287</SRS>
+      <SRS>EPSG:2288</SRS>
+      <SRS>EPSG:2289</SRS>
+      <SRS>EPSG:2290</SRS>
+      <SRS>EPSG:2291</SRS>
+      <SRS>EPSG:2292</SRS>
+      <SRS>EPSG:2294</SRS>
+      <SRS>EPSG:2295</SRS>
+      <SRS>EPSG:2296</SRS>
+      <SRS>EPSG:2297</SRS>
+      <SRS>EPSG:2298</SRS>
+      <SRS>EPSG:2299</SRS>
+      <SRS>EPSG:2300</SRS>
+      <SRS>EPSG:2301</SRS>
+      <SRS>EPSG:2302</SRS>
+      <SRS>EPSG:2303</SRS>
+      <SRS>EPSG:2304</SRS>
+      <SRS>EPSG:2305</SRS>
+      <SRS>EPSG:2306</SRS>
+      <SRS>EPSG:2307</SRS>
+      <SRS>EPSG:2308</SRS>
+      <SRS>EPSG:2309</SRS>
+      <SRS>EPSG:2310</SRS>
+      <SRS>EPSG:2311</SRS>
+      <SRS>EPSG:2312</SRS>
+      <SRS>EPSG:2313</SRS>
+      <SRS>EPSG:2314</SRS>
+      <SRS>EPSG:2315</SRS>
+      <SRS>EPSG:2316</SRS>
+      <SRS>EPSG:2317</SRS>
+      <SRS>EPSG:2318</SRS>
+      <SRS>EPSG:2319</SRS>
+      <SRS>EPSG:2320</SRS>
+      <SRS>EPSG:2321</SRS>
+      <SRS>EPSG:2322</SRS>
+      <SRS>EPSG:2323</SRS>
+      <SRS>EPSG:2324</SRS>
+      <SRS>EPSG:2325</SRS>
+      <SRS>EPSG:2326</SRS>
+      <SRS>EPSG:2327</SRS>
+      <SRS>EPSG:2328</SRS>
+      <SRS>EPSG:2329</SRS>
+      <SRS>EPSG:2330</SRS>
+      <SRS>EPSG:2331</SRS>
+      <SRS>EPSG:2332</SRS>
+      <SRS>EPSG:2333</SRS>
+      <SRS>EPSG:2334</SRS>
+      <SRS>EPSG:2335</SRS>
+      <SRS>EPSG:2336</SRS>
+      <SRS>EPSG:2337</SRS>
+      <SRS>EPSG:2338</SRS>
+      <SRS>EPSG:2339</SRS>
+      <SRS>EPSG:2340</SRS>
+      <SRS>EPSG:2341</SRS>
+      <SRS>EPSG:2342</SRS>
+      <SRS>EPSG:2343</SRS>
+      <SRS>EPSG:2344</SRS>
+      <SRS>EPSG:2345</SRS>
+      <SRS>EPSG:2346</SRS>
+      <SRS>EPSG:2347</SRS>
+      <SRS>EPSG:2348</SRS>
+      <SRS>EPSG:2349</SRS>
+      <SRS>EPSG:2350</SRS>
+      <SRS>EPSG:2351</SRS>
+      <SRS>EPSG:2352</SRS>
+      <SRS>EPSG:2353</SRS>
+      <SRS>EPSG:2354</SRS>
+      <SRS>EPSG:2355</SRS>
+      <SRS>EPSG:2356</SRS>
+      <SRS>EPSG:2357</SRS>
+      <SRS>EPSG:2358</SRS>
+      <SRS>EPSG:2359</SRS>
+      <SRS>EPSG:2360</SRS>
+      <SRS>EPSG:2361</SRS>
+      <SRS>EPSG:2362</SRS>
+      <SRS>EPSG:2363</SRS>
+      <SRS>EPSG:2364</SRS>
+      <SRS>EPSG:2365</SRS>
+      <SRS>EPSG:2366</SRS>
+      <SRS>EPSG:2367</SRS>
+      <SRS>EPSG:2368</SRS>
+      <SRS>EPSG:2369</SRS>
+      <SRS>EPSG:2370</SRS>
+      <SRS>EPSG:2371</SRS>
+      <SRS>EPSG:2372</SRS>
+      <SRS>EPSG:2373</SRS>
+      <SRS>EPSG:2374</SRS>
+      <SRS>EPSG:2375</SRS>
+      <SRS>EPSG:2376</SRS>
+      <SRS>EPSG:2377</SRS>
+      <SRS>EPSG:2378</SRS>
+      <SRS>EPSG:2379</SRS>
+      <SRS>EPSG:2380</SRS>
+      <SRS>EPSG:2381</SRS>
+      <SRS>EPSG:2382</SRS>
+      <SRS>EPSG:2383</SRS>
+      <SRS>EPSG:2384</SRS>
+      <SRS>EPSG:2385</SRS>
+      <SRS>EPSG:2386</SRS>
+      <SRS>EPSG:2387</SRS>
+      <SRS>EPSG:2388</SRS>
+      <SRS>EPSG:2389</SRS>
+      <SRS>EPSG:2390</SRS>
+      <SRS>EPSG:2391</SRS>
+      <SRS>EPSG:2392</SRS>
+      <SRS>EPSG:2393</SRS>
+      <SRS>EPSG:2394</SRS>
+      <SRS>EPSG:2395</SRS>
+      <SRS>EPSG:2396</SRS>
+      <SRS>EPSG:2397</SRS>
+      <SRS>EPSG:2398</SRS>
+      <SRS>EPSG:2399</SRS>
+      <SRS>EPSG:2400</SRS>
+      <SRS>EPSG:2401</SRS>
+      <SRS>EPSG:2402</SRS>
+      <SRS>EPSG:2403</SRS>
+      <SRS>EPSG:2404</SRS>
+      <SRS>EPSG:2405</SRS>
+      <SRS>EPSG:2406</SRS>
+      <SRS>EPSG:2407</SRS>
+      <SRS>EPSG:2408</SRS>
+      <SRS>EPSG:2409</SRS>
+      <SRS>EPSG:2410</SRS>
+      <SRS>EPSG:2411</SRS>
+      <SRS>EPSG:2412</SRS>
+      <SRS>EPSG:2413</SRS>
+      <SRS>EPSG:2414</SRS>
+      <SRS>EPSG:2415</SRS>
+      <SRS>EPSG:2416</SRS>
+      <SRS>EPSG:2417</SRS>
+      <SRS>EPSG:2418</SRS>
+      <SRS>EPSG:2419</SRS>
+      <SRS>EPSG:2420</SRS>
+      <SRS>EPSG:2421</SRS>
+      <SRS>EPSG:2422</SRS>
+      <SRS>EPSG:2423</SRS>
+      <SRS>EPSG:2424</SRS>
+      <SRS>EPSG:2425</SRS>
+      <SRS>EPSG:2426</SRS>
+      <SRS>EPSG:2427</SRS>
+      <SRS>EPSG:2428</SRS>
+      <SRS>EPSG:2429</SRS>
+      <SRS>EPSG:2430</SRS>
+      <SRS>EPSG:2431</SRS>
+      <SRS>EPSG:2432</SRS>
+      <SRS>EPSG:2433</SRS>
+      <SRS>EPSG:2434</SRS>
+      <SRS>EPSG:2435</SRS>
+      <SRS>EPSG:2436</SRS>
+      <SRS>EPSG:2437</SRS>
+      <SRS>EPSG:2438</SRS>
+      <SRS>EPSG:2439</SRS>
+      <SRS>EPSG:2440</SRS>
+      <SRS>EPSG:2441</SRS>
+      <SRS>EPSG:2442</SRS>
+      <SRS>EPSG:2443</SRS>
+      <SRS>EPSG:2444</SRS>
+      <SRS>EPSG:2445</SRS>
+      <SRS>EPSG:2446</SRS>
+      <SRS>EPSG:2447</SRS>
+      <SRS>EPSG:2448</SRS>
+      <SRS>EPSG:2449</SRS>
+      <SRS>EPSG:2450</SRS>
+      <SRS>EPSG:2451</SRS>
+      <SRS>EPSG:2452</SRS>
+      <SRS>EPSG:2453</SRS>
+      <SRS>EPSG:2454</SRS>
+      <SRS>EPSG:2455</SRS>
+      <SRS>EPSG:2456</SRS>
+      <SRS>EPSG:2457</SRS>
+      <SRS>EPSG:2458</SRS>
+      <SRS>EPSG:2459</SRS>
+      <SRS>EPSG:2460</SRS>
+      <SRS>EPSG:2461</SRS>
+      <SRS>EPSG:2462</SRS>
+      <SRS>EPSG:2463</SRS>
+      <SRS>EPSG:2464</SRS>
+      <SRS>EPSG:2465</SRS>
+      <SRS>EPSG:2466</SRS>
+      <SRS>EPSG:2467</SRS>
+      <SRS>EPSG:2468</SRS>
+      <SRS>EPSG:2469</SRS>
+      <SRS>EPSG:2470</SRS>
+      <SRS>EPSG:2471</SRS>
+      <SRS>EPSG:2472</SRS>
+      <SRS>EPSG:2473</SRS>
+      <SRS>EPSG:2474</SRS>
+      <SRS>EPSG:2475</SRS>
+      <SRS>EPSG:2476</SRS>
+      <SRS>EPSG:2477</SRS>
+      <SRS>EPSG:2478</SRS>
+      <SRS>EPSG:2479</SRS>
+      <SRS>EPSG:2480</SRS>
+      <SRS>EPSG:2481</SRS>
+      <SRS>EPSG:2482</SRS>
+      <SRS>EPSG:2483</SRS>
+      <SRS>EPSG:2484</SRS>
+      <SRS>EPSG:2485</SRS>
+      <SRS>EPSG:2486</SRS>
+      <SRS>EPSG:2487</SRS>
+      <SRS>EPSG:2488</SRS>
+      <SRS>EPSG:2489</SRS>
+      <SRS>EPSG:2490</SRS>
+      <SRS>EPSG:2491</SRS>
+      <SRS>EPSG:2492</SRS>
+      <SRS>EPSG:2493</SRS>
+      <SRS>EPSG:2494</SRS>
+      <SRS>EPSG:2495</SRS>
+      <SRS>EPSG:2496</SRS>
+      <SRS>EPSG:2497</SRS>
+      <SRS>EPSG:2498</SRS>
+      <SRS>EPSG:2499</SRS>
+      <SRS>EPSG:2500</SRS>
+      <SRS>EPSG:2501</SRS>
+      <SRS>EPSG:2502</SRS>
+      <SRS>EPSG:2503</SRS>
+      <SRS>EPSG:2504</SRS>
+      <SRS>EPSG:2505</SRS>
+      <SRS>EPSG:2506</SRS>
+      <SRS>EPSG:2507</SRS>
+      <SRS>EPSG:2508</SRS>
+      <SRS>EPSG:2509</SRS>
+      <SRS>EPSG:2510</SRS>
+      <SRS>EPSG:2511</SRS>
+      <SRS>EPSG:2512</SRS>
+      <SRS>EPSG:2513</SRS>
+      <SRS>EPSG:2514</SRS>
+      <SRS>EPSG:2515</SRS>
+      <SRS>EPSG:2516</SRS>
+      <SRS>EPSG:2517</SRS>
+      <SRS>EPSG:2518</SRS>
+      <SRS>EPSG:2519</SRS>
+      <SRS>EPSG:2520</SRS>
+      <SRS>EPSG:2521</SRS>
+      <SRS>EPSG:2522</SRS>
+      <SRS>EPSG:2523</SRS>
+      <SRS>EPSG:2524</SRS>
+      <SRS>EPSG:2525</SRS>
+      <SRS>EPSG:2526</SRS>
+      <SRS>EPSG:2527</SRS>
+      <SRS>EPSG:2528</SRS>
+      <SRS>EPSG:2529</SRS>
+      <SRS>EPSG:2530</SRS>
+      <SRS>EPSG:2531</SRS>
+      <SRS>EPSG:2532</SRS>
+      <SRS>EPSG:2533</SRS>
+      <SRS>EPSG:2534</SRS>
+      <SRS>EPSG:2535</SRS>
+      <SRS>EPSG:2536</SRS>
+      <SRS>EPSG:2537</SRS>
+      <SRS>EPSG:2538</SRS>
+      <SRS>EPSG:2539</SRS>
+      <SRS>EPSG:2540</SRS>
+      <SRS>EPSG:2541</SRS>
+      <SRS>EPSG:2542</SRS>
+      <SRS>EPSG:2543</SRS>
+      <SRS>EPSG:2544</SRS>
+      <SRS>EPSG:2545</SRS>
+      <SRS>EPSG:2546</SRS>
+      <SRS>EPSG:2547</SRS>
+      <SRS>EPSG:2548</SRS>
+      <SRS>EPSG:2549</SRS>
+      <SRS>EPSG:2550</SRS>
+      <SRS>EPSG:2551</SRS>
+      <SRS>EPSG:2552</SRS>
+      <SRS>EPSG:2553</SRS>
+      <SRS>EPSG:2554</SRS>
+      <SRS>EPSG:2555</SRS>
+      <SRS>EPSG:2556</SRS>
+      <SRS>EPSG:2557</SRS>
+      <SRS>EPSG:2558</SRS>
+      <SRS>EPSG:2559</SRS>
+      <SRS>EPSG:2560</SRS>
+      <SRS>EPSG:2561</SRS>
+      <SRS>EPSG:2562</SRS>
+      <SRS>EPSG:2563</SRS>
+      <SRS>EPSG:2564</SRS>
+      <SRS>EPSG:2565</SRS>
+      <SRS>EPSG:2566</SRS>
+      <SRS>EPSG:2567</SRS>
+      <SRS>EPSG:2568</SRS>
+      <SRS>EPSG:2569</SRS>
+      <SRS>EPSG:2570</SRS>
+      <SRS>EPSG:2571</SRS>
+      <SRS>EPSG:2572</SRS>
+      <SRS>EPSG:2573</SRS>
+      <SRS>EPSG:2574</SRS>
+      <SRS>EPSG:2575</SRS>
+      <SRS>EPSG:2576</SRS>
+      <SRS>EPSG:2577</SRS>
+      <SRS>EPSG:2578</SRS>
+      <SRS>EPSG:2579</SRS>
+      <SRS>EPSG:2580</SRS>
+      <SRS>EPSG:2581</SRS>
+      <SRS>EPSG:2582</SRS>
+      <SRS>EPSG:2583</SRS>
+      <SRS>EPSG:2584</SRS>
+      <SRS>EPSG:2585</SRS>
+      <SRS>EPSG:2586</SRS>
+      <SRS>EPSG:2587</SRS>
+      <SRS>EPSG:2588</SRS>
+      <SRS>EPSG:2589</SRS>
+      <SRS>EPSG:2590</SRS>
+      <SRS>EPSG:2591</SRS>
+      <SRS>EPSG:2592</SRS>
+      <SRS>EPSG:2593</SRS>
+      <SRS>EPSG:2594</SRS>
+      <SRS>EPSG:2595</SRS>
+      <SRS>EPSG:2596</SRS>
+      <SRS>EPSG:2597</SRS>
+      <SRS>EPSG:2598</SRS>
+      <SRS>EPSG:2599</SRS>
+      <SRS>EPSG:2600</SRS>
+      <SRS>EPSG:2601</SRS>
+      <SRS>EPSG:2602</SRS>
+      <SRS>EPSG:2603</SRS>
+      <SRS>EPSG:2604</SRS>
+      <SRS>EPSG:2605</SRS>
+      <SRS>EPSG:2606</SRS>
+      <SRS>EPSG:2607</SRS>
+      <SRS>EPSG:2608</SRS>
+      <SRS>EPSG:2609</SRS>
+      <SRS>EPSG:2610</SRS>
+      <SRS>EPSG:2611</SRS>
+      <SRS>EPSG:2612</SRS>
+      <SRS>EPSG:2613</SRS>
+      <SRS>EPSG:2614</SRS>
+      <SRS>EPSG:2615</SRS>
+      <SRS>EPSG:2616</SRS>
+      <SRS>EPSG:2617</SRS>
+      <SRS>EPSG:2618</SRS>
+      <SRS>EPSG:2619</SRS>
+      <SRS>EPSG:2620</SRS>
+      <SRS>EPSG:2621</SRS>
+      <SRS>EPSG:2622</SRS>
+      <SRS>EPSG:2623</SRS>
+      <SRS>EPSG:2624</SRS>
+      <SRS>EPSG:2625</SRS>
+      <SRS>EPSG:2626</SRS>
+      <SRS>EPSG:2627</SRS>
+      <SRS>EPSG:2628</SRS>
+      <SRS>EPSG:2629</SRS>
+      <SRS>EPSG:2630</SRS>
+      <SRS>EPSG:2631</SRS>
+      <SRS>EPSG:2632</SRS>
+      <SRS>EPSG:2633</SRS>
+      <SRS>EPSG:2634</SRS>
+      <SRS>EPSG:2635</SRS>
+      <SRS>EPSG:2636</SRS>
+      <SRS>EPSG:2637</SRS>
+      <SRS>EPSG:2638</SRS>
+      <SRS>EPSG:2639</SRS>
+      <SRS>EPSG:2640</SRS>
+      <SRS>EPSG:2641</SRS>
+      <SRS>EPSG:2642</SRS>
+      <SRS>EPSG:2643</SRS>
+      <SRS>EPSG:2644</SRS>
+      <SRS>EPSG:2645</SRS>
+      <SRS>EPSG:2646</SRS>
+      <SRS>EPSG:2647</SRS>
+      <SRS>EPSG:2648</SRS>
+      <SRS>EPSG:2649</SRS>
+      <SRS>EPSG:2650</SRS>
+      <SRS>EPSG:2651</SRS>
+      <SRS>EPSG:2652</SRS>
+      <SRS>EPSG:2653</SRS>
+      <SRS>EPSG:2654</SRS>
+      <SRS>EPSG:2655</SRS>
+      <SRS>EPSG:2656</SRS>
+      <SRS>EPSG:2657</SRS>
+      <SRS>EPSG:2658</SRS>
+      <SRS>EPSG:2659</SRS>
+      <SRS>EPSG:2660</SRS>
+      <SRS>EPSG:2661</SRS>
+      <SRS>EPSG:2662</SRS>
+      <SRS>EPSG:2663</SRS>
+      <SRS>EPSG:2664</SRS>
+      <SRS>EPSG:2665</SRS>
+      <SRS>EPSG:2666</SRS>
+      <SRS>EPSG:2667</SRS>
+      <SRS>EPSG:2668</SRS>
+      <SRS>EPSG:2669</SRS>
+      <SRS>EPSG:2670</SRS>
+      <SRS>EPSG:2671</SRS>
+      <SRS>EPSG:2672</SRS>
+      <SRS>EPSG:2673</SRS>
+      <SRS>EPSG:2674</SRS>
+      <SRS>EPSG:2675</SRS>
+      <SRS>EPSG:2676</SRS>
+      <SRS>EPSG:2677</SRS>
+      <SRS>EPSG:2678</SRS>
+      <SRS>EPSG:2679</SRS>
+      <SRS>EPSG:2680</SRS>
+      <SRS>EPSG:2681</SRS>
+      <SRS>EPSG:2682</SRS>
+      <SRS>EPSG:2683</SRS>
+      <SRS>EPSG:2684</SRS>
+      <SRS>EPSG:2685</SRS>
+      <SRS>EPSG:2686</SRS>
+      <SRS>EPSG:2687</SRS>
+      <SRS>EPSG:2688</SRS>
+      <SRS>EPSG:2689</SRS>
+      <SRS>EPSG:2690</SRS>
+      <SRS>EPSG:2691</SRS>
+      <SRS>EPSG:2692</SRS>
+      <SRS>EPSG:2693</SRS>
+      <SRS>EPSG:2694</SRS>
+      <SRS>EPSG:2695</SRS>
+      <SRS>EPSG:2696</SRS>
+      <SRS>EPSG:2697</SRS>
+      <SRS>EPSG:2698</SRS>
+      <SRS>EPSG:2699</SRS>
+      <SRS>EPSG:2700</SRS>
+      <SRS>EPSG:2701</SRS>
+      <SRS>EPSG:2702</SRS>
+      <SRS>EPSG:2703</SRS>
+      <SRS>EPSG:2704</SRS>
+      <SRS>EPSG:2705</SRS>
+      <SRS>EPSG:2706</SRS>
+      <SRS>EPSG:2707</SRS>
+      <SRS>EPSG:2708</SRS>
+      <SRS>EPSG:2709</SRS>
+      <SRS>EPSG:2710</SRS>
+      <SRS>EPSG:2711</SRS>
+      <SRS>EPSG:2712</SRS>
+      <SRS>EPSG:2713</SRS>
+      <SRS>EPSG:2714</SRS>
+      <SRS>EPSG:2715</SRS>
+      <SRS>EPSG:2716</SRS>
+      <SRS>EPSG:2717</SRS>
+      <SRS>EPSG:2718</SRS>
+      <SRS>EPSG:2719</SRS>
+      <SRS>EPSG:2720</SRS>
+      <SRS>EPSG:2721</SRS>
+      <SRS>EPSG:2722</SRS>
+      <SRS>EPSG:2723</SRS>
+      <SRS>EPSG:2724</SRS>
+      <SRS>EPSG:2725</SRS>
+      <SRS>EPSG:2726</SRS>
+      <SRS>EPSG:2727</SRS>
+      <SRS>EPSG:2728</SRS>
+      <SRS>EPSG:2729</SRS>
+      <SRS>EPSG:2730</SRS>
+      <SRS>EPSG:2731</SRS>
+      <SRS>EPSG:2732</SRS>
+      <SRS>EPSG:2733</SRS>
+      <SRS>EPSG:2734</SRS>
+      <SRS>EPSG:2735</SRS>
+      <SRS>EPSG:2736</SRS>
+      <SRS>EPSG:2737</SRS>
+      <SRS>EPSG:2738</SRS>
+      <SRS>EPSG:2739</SRS>
+      <SRS>EPSG:2740</SRS>
+      <SRS>EPSG:2741</SRS>
+      <SRS>EPSG:2742</SRS>
+      <SRS>EPSG:2743</SRS>
+      <SRS>EPSG:2744</SRS>
+      <SRS>EPSG:2745</SRS>
+      <SRS>EPSG:2746</SRS>
+      <SRS>EPSG:2747</SRS>
+      <SRS>EPSG:2748</SRS>
+      <SRS>EPSG:2749</SRS>
+      <SRS>EPSG:2750</SRS>
+      <SRS>EPSG:2751</SRS>
+      <SRS>EPSG:2752</SRS>
+      <SRS>EPSG:2753</SRS>
+      <SRS>EPSG:2754</SRS>
+      <SRS>EPSG:2755</SRS>
+      <SRS>EPSG:2756</SRS>
+      <SRS>EPSG:2757</SRS>
+      <SRS>EPSG:2758</SRS>
+      <SRS>EPSG:2759</SRS>
+      <SRS>EPSG:2760</SRS>
+      <SRS>EPSG:2761</SRS>
+      <SRS>EPSG:2762</SRS>
+      <SRS>EPSG:2763</SRS>
+      <SRS>EPSG:2764</SRS>
+      <SRS>EPSG:2765</SRS>
+      <SRS>EPSG:2766</SRS>
+      <SRS>EPSG:2767</SRS>
+      <SRS>EPSG:2768</SRS>
+      <SRS>EPSG:2769</SRS>
+      <SRS>EPSG:2770</SRS>
+      <SRS>EPSG:2771</SRS>
+      <SRS>EPSG:2772</SRS>
+      <SRS>EPSG:2773</SRS>
+      <SRS>EPSG:2774</SRS>
+      <SRS>EPSG:2775</SRS>
+      <SRS>EPSG:2776</SRS>
+      <SRS>EPSG:2777</SRS>
+      <SRS>EPSG:2778</SRS>
+      <SRS>EPSG:2779</SRS>
+      <SRS>EPSG:2780</SRS>
+      <SRS>EPSG:2781</SRS>
+      <SRS>EPSG:2782</SRS>
+      <SRS>EPSG:2783</SRS>
+      <SRS>EPSG:2784</SRS>
+      <SRS>EPSG:2785</SRS>
+      <SRS>EPSG:2786</SRS>
+      <SRS>EPSG:2787</SRS>
+      <SRS>EPSG:2788</SRS>
+      <SRS>EPSG:2789</SRS>
+      <SRS>EPSG:2790</SRS>
+      <SRS>EPSG:2791</SRS>
+      <SRS>EPSG:2792</SRS>
+      <SRS>EPSG:2793</SRS>
+      <SRS>EPSG:2794</SRS>
+      <SRS>EPSG:2795</SRS>
+      <SRS>EPSG:2796</SRS>
+      <SRS>EPSG:2797</SRS>
+      <SRS>EPSG:2798</SRS>
+      <SRS>EPSG:2799</SRS>
+      <SRS>EPSG:2800</SRS>
+      <SRS>EPSG:2801</SRS>
+      <SRS>EPSG:2802</SRS>
+      <SRS>EPSG:2803</SRS>
+      <SRS>EPSG:2804</SRS>
+      <SRS>EPSG:2805</SRS>
+      <SRS>EPSG:2806</SRS>
+      <SRS>EPSG:2807</SRS>
+      <SRS>EPSG:2808</SRS>
+      <SRS>EPSG:2809</SRS>
+      <SRS>EPSG:2810</SRS>
+      <SRS>EPSG:2811</SRS>
+      <SRS>EPSG:2812</SRS>
+      <SRS>EPSG:2813</SRS>
+      <SRS>EPSG:2814</SRS>
+      <SRS>EPSG:2815</SRS>
+      <SRS>EPSG:2816</SRS>
+      <SRS>EPSG:2817</SRS>
+      <SRS>EPSG:2818</SRS>
+      <SRS>EPSG:2819</SRS>
+      <SRS>EPSG:2820</SRS>
+      <SRS>EPSG:2821</SRS>
+      <SRS>EPSG:2822</SRS>
+      <SRS>EPSG:2823</SRS>
+      <SRS>EPSG:2824</SRS>
+      <SRS>EPSG:2825</SRS>
+      <SRS>EPSG:2826</SRS>
+      <SRS>EPSG:2827</SRS>
+      <SRS>EPSG:2828</SRS>
+      <SRS>EPSG:2829</SRS>
+      <SRS>EPSG:2830</SRS>
+      <SRS>EPSG:2831</SRS>
+      <SRS>EPSG:2832</SRS>
+      <SRS>EPSG:2833</SRS>
+      <SRS>EPSG:2834</SRS>
+      <SRS>EPSG:2835</SRS>
+      <SRS>EPSG:2836</SRS>
+      <SRS>EPSG:2837</SRS>
+      <SRS>EPSG:2838</SRS>
+      <SRS>EPSG:2839</SRS>
+      <SRS>EPSG:2840</SRS>
+      <SRS>EPSG:2841</SRS>
+      <SRS>EPSG:2842</SRS>
+      <SRS>EPSG:2843</SRS>
+      <SRS>EPSG:2844</SRS>
+      <SRS>EPSG:2845</SRS>
+      <SRS>EPSG:2846</SRS>
+      <SRS>EPSG:2847</SRS>
+      <SRS>EPSG:2848</SRS>
+      <SRS>EPSG:2849</SRS>
+      <SRS>EPSG:2850</SRS>
+      <SRS>EPSG:2851</SRS>
+      <SRS>EPSG:2852</SRS>
+      <SRS>EPSG:2853</SRS>
+      <SRS>EPSG:2854</SRS>
+      <SRS>EPSG:2855</SRS>
+      <SRS>EPSG:2856</SRS>
+      <SRS>EPSG:2857</SRS>
+      <SRS>EPSG:2858</SRS>
+      <SRS>EPSG:2859</SRS>
+      <SRS>EPSG:2860</SRS>
+      <SRS>EPSG:2861</SRS>
+      <SRS>EPSG:2862</SRS>
+      <SRS>EPSG:2863</SRS>
+      <SRS>EPSG:2864</SRS>
+      <SRS>EPSG:2865</SRS>
+      <SRS>EPSG:2866</SRS>
+      <SRS>EPSG:2867</SRS>
+      <SRS>EPSG:2868</SRS>
+      <SRS>EPSG:2869</SRS>
+      <SRS>EPSG:2870</SRS>
+      <SRS>EPSG:2871</SRS>
+      <SRS>EPSG:2872</SRS>
+      <SRS>EPSG:2873</SRS>
+      <SRS>EPSG:2874</SRS>
+      <SRS>EPSG:2875</SRS>
+      <SRS>EPSG:2876</SRS>
+      <SRS>EPSG:2877</SRS>
+      <SRS>EPSG:2878</SRS>
+      <SRS>EPSG:2879</SRS>
+      <SRS>EPSG:2880</SRS>
+      <SRS>EPSG:2881</SRS>
+      <SRS>EPSG:2882</SRS>
+      <SRS>EPSG:2883</SRS>
+      <SRS>EPSG:2884</SRS>
+      <SRS>EPSG:2885</SRS>
+      <SRS>EPSG:2886</SRS>
+      <SRS>EPSG:2887</SRS>
+      <SRS>EPSG:2888</SRS>
+      <SRS>EPSG:2889</SRS>
+      <SRS>EPSG:2890</SRS>
+      <SRS>EPSG:2891</SRS>
+      <SRS>EPSG:2892</SRS>
+      <SRS>EPSG:2893</SRS>
+      <SRS>EPSG:2894</SRS>
+      <SRS>EPSG:2895</SRS>
+      <SRS>EPSG:2896</SRS>
+      <SRS>EPSG:2897</SRS>
+      <SRS>EPSG:2898</SRS>
+      <SRS>EPSG:2899</SRS>
+      <SRS>EPSG:2900</SRS>
+      <SRS>EPSG:2901</SRS>
+      <SRS>EPSG:2902</SRS>
+      <SRS>EPSG:2903</SRS>
+      <SRS>EPSG:2904</SRS>
+      <SRS>EPSG:2905</SRS>
+      <SRS>EPSG:2906</SRS>
+      <SRS>EPSG:2907</SRS>
+      <SRS>EPSG:2908</SRS>
+      <SRS>EPSG:2909</SRS>
+      <SRS>EPSG:2910</SRS>
+      <SRS>EPSG:2911</SRS>
+      <SRS>EPSG:2912</SRS>
+      <SRS>EPSG:2913</SRS>
+      <SRS>EPSG:2914</SRS>
+      <SRS>EPSG:2915</SRS>
+      <SRS>EPSG:2916</SRS>
+      <SRS>EPSG:2917</SRS>
+      <SRS>EPSG:2918</SRS>
+      <SRS>EPSG:2919</SRS>
+      <SRS>EPSG:2920</SRS>
+      <SRS>EPSG:2921</SRS>
+      <SRS>EPSG:2922</SRS>
+      <SRS>EPSG:2923</SRS>
+      <SRS>EPSG:2924</SRS>
+      <SRS>EPSG:2925</SRS>
+      <SRS>EPSG:2926</SRS>
+      <SRS>EPSG:2927</SRS>
+      <SRS>EPSG:2928</SRS>
+      <SRS>EPSG:2929</SRS>
+      <SRS>EPSG:2930</SRS>
+      <SRS>EPSG:2931</SRS>
+      <SRS>EPSG:2932</SRS>
+      <SRS>EPSG:2933</SRS>
+      <SRS>EPSG:2934</SRS>
+      <SRS>EPSG:2935</SRS>
+      <SRS>EPSG:2936</SRS>
+      <SRS>EPSG:2937</SRS>
+      <SRS>EPSG:2938</SRS>
+      <SRS>EPSG:2939</SRS>
+      <SRS>EPSG:2940</SRS>
+      <SRS>EPSG:2941</SRS>
+      <SRS>EPSG:2942</SRS>
+      <SRS>EPSG:2943</SRS>
+      <SRS>EPSG:2944</SRS>
+      <SRS>EPSG:2945</SRS>
+      <SRS>EPSG:2946</SRS>
+      <SRS>EPSG:2947</SRS>
+      <SRS>EPSG:2948</SRS>
+      <SRS>EPSG:2949</SRS>
+      <SRS>EPSG:2950</SRS>
+      <SRS>EPSG:2951</SRS>
+      <SRS>EPSG:2952</SRS>
+      <SRS>EPSG:2953</SRS>
+      <SRS>EPSG:2954</SRS>
+      <SRS>EPSG:2955</SRS>
+      <SRS>EPSG:2956</SRS>
+      <SRS>EPSG:2957</SRS>
+      <SRS>EPSG:2958</SRS>
+      <SRS>EPSG:2959</SRS>
+      <SRS>EPSG:2960</SRS>
+      <SRS>EPSG:2961</SRS>
+      <SRS>EPSG:2962</SRS>
+      <SRS>EPSG:2963</SRS>
+      <SRS>EPSG:2964</SRS>
+      <SRS>EPSG:2965</SRS>
+      <SRS>EPSG:2966</SRS>
+      <SRS>EPSG:2967</SRS>
+      <SRS>EPSG:2968</SRS>
+      <SRS>EPSG:2969</SRS>
+      <SRS>EPSG:2970</SRS>
+      <SRS>EPSG:2971</SRS>
+      <SRS>EPSG:2972</SRS>
+      <SRS>EPSG:2973</SRS>
+      <SRS>EPSG:2975</SRS>
+      <SRS>EPSG:2976</SRS>
+      <SRS>EPSG:2977</SRS>
+      <SRS>EPSG:2978</SRS>
+      <SRS>EPSG:2979</SRS>
+      <SRS>EPSG:2980</SRS>
+      <SRS>EPSG:2981</SRS>
+      <SRS>EPSG:2982</SRS>
+      <SRS>EPSG:2983</SRS>
+      <SRS>EPSG:2984</SRS>
+      <SRS>EPSG:2985</SRS>
+      <SRS>EPSG:2986</SRS>
+      <SRS>EPSG:2987</SRS>
+      <SRS>EPSG:2988</SRS>
+      <SRS>EPSG:2989</SRS>
+      <SRS>EPSG:2990</SRS>
+      <SRS>EPSG:2991</SRS>
+      <SRS>EPSG:2992</SRS>
+      <SRS>EPSG:2993</SRS>
+      <SRS>EPSG:2994</SRS>
+      <SRS>EPSG:2995</SRS>
+      <SRS>EPSG:2996</SRS>
+      <SRS>EPSG:2997</SRS>
+      <SRS>EPSG:2998</SRS>
+      <SRS>EPSG:2999</SRS>
+      <SRS>EPSG:3000</SRS>
+      <SRS>EPSG:3001</SRS>
+      <SRS>EPSG:3002</SRS>
+      <SRS>EPSG:3003</SRS>
+      <SRS>EPSG:3004</SRS>
+      <SRS>EPSG:3005</SRS>
+      <SRS>EPSG:3006</SRS>
+      <SRS>EPSG:3007</SRS>
+      <SRS>EPSG:3008</SRS>
+      <SRS>EPSG:3009</SRS>
+      <SRS>EPSG:3010</SRS>
+      <SRS>EPSG:3011</SRS>
+      <SRS>EPSG:3012</SRS>
+      <SRS>EPSG:3013</SRS>
+      <SRS>EPSG:3014</SRS>
+      <SRS>EPSG:3015</SRS>
+      <SRS>EPSG:3016</SRS>
+      <SRS>EPSG:3017</SRS>
+      <SRS>EPSG:3018</SRS>
+      <SRS>EPSG:3019</SRS>
+      <SRS>EPSG:3020</SRS>
+      <SRS>EPSG:3021</SRS>
+      <SRS>EPSG:3022</SRS>
+      <SRS>EPSG:3023</SRS>
+      <SRS>EPSG:3024</SRS>
+      <SRS>EPSG:3025</SRS>
+      <SRS>EPSG:3026</SRS>
+      <SRS>EPSG:3027</SRS>
+      <SRS>EPSG:3028</SRS>
+      <SRS>EPSG:3029</SRS>
+      <SRS>EPSG:3030</SRS>
+      <SRS>EPSG:3031</SRS>
+      <SRS>EPSG:3032</SRS>
+      <SRS>EPSG:3033</SRS>
+      <SRS>EPSG:3034</SRS>
+      <SRS>EPSG:3035</SRS>
+      <SRS>EPSG:3036</SRS>
+      <SRS>EPSG:3037</SRS>
+      <SRS>EPSG:3038</SRS>
+      <SRS>EPSG:3039</SRS>
+      <SRS>EPSG:3040</SRS>
+      <SRS>EPSG:3041</SRS>
+      <SRS>EPSG:3042</SRS>
+      <SRS>EPSG:3043</SRS>
+      <SRS>EPSG:3044</SRS>
+      <SRS>EPSG:3045</SRS>
+      <SRS>EPSG:3046</SRS>
+      <SRS>EPSG:3047</SRS>
+      <SRS>EPSG:3048</SRS>
+      <SRS>EPSG:3049</SRS>
+      <SRS>EPSG:3050</SRS>
+      <SRS>EPSG:3051</SRS>
+      <SRS>EPSG:3052</SRS>
+      <SRS>EPSG:3053</SRS>
+      <SRS>EPSG:3054</SRS>
+      <SRS>EPSG:3055</SRS>
+      <SRS>EPSG:3056</SRS>
+      <SRS>EPSG:3057</SRS>
+      <SRS>EPSG:3058</SRS>
+      <SRS>EPSG:3059</SRS>
+      <SRS>EPSG:3060</SRS>
+      <SRS>EPSG:3061</SRS>
+      <SRS>EPSG:3062</SRS>
+      <SRS>EPSG:3063</SRS>
+      <SRS>EPSG:3064</SRS>
+      <SRS>EPSG:3065</SRS>
+      <SRS>EPSG:3066</SRS>
+      <SRS>EPSG:3067</SRS>
+      <SRS>EPSG:3068</SRS>
+      <SRS>EPSG:3069</SRS>
+      <SRS>EPSG:3070</SRS>
+      <SRS>EPSG:3071</SRS>
+      <SRS>EPSG:3072</SRS>
+      <SRS>EPSG:3073</SRS>
+      <SRS>EPSG:3074</SRS>
+      <SRS>EPSG:3075</SRS>
+      <SRS>EPSG:3076</SRS>
+      <SRS>EPSG:3077</SRS>
+      <SRS>EPSG:3078</SRS>
+      <SRS>EPSG:3079</SRS>
+      <SRS>EPSG:3080</SRS>
+      <SRS>EPSG:3081</SRS>
+      <SRS>EPSG:3082</SRS>
+      <SRS>EPSG:3083</SRS>
+      <SRS>EPSG:3084</SRS>
+      <SRS>EPSG:3085</SRS>
+      <SRS>EPSG:3086</SRS>
+      <SRS>EPSG:3087</SRS>
+      <SRS>EPSG:3088</SRS>
+      <SRS>EPSG:3089</SRS>
+      <SRS>EPSG:3090</SRS>
+      <SRS>EPSG:3091</SRS>
+      <SRS>EPSG:3092</SRS>
+      <SRS>EPSG:3093</SRS>
+      <SRS>EPSG:3094</SRS>
+      <SRS>EPSG:3095</SRS>
+      <SRS>EPSG:3096</SRS>
+      <SRS>EPSG:3097</SRS>
+      <SRS>EPSG:3098</SRS>
+      <SRS>EPSG:3099</SRS>
+      <SRS>EPSG:3100</SRS>
+      <SRS>EPSG:3101</SRS>
+      <SRS>EPSG:3102</SRS>
+      <SRS>EPSG:3103</SRS>
+      <SRS>EPSG:3104</SRS>
+      <SRS>EPSG:3105</SRS>
+      <SRS>EPSG:3106</SRS>
+      <SRS>EPSG:3107</SRS>
+      <SRS>EPSG:3108</SRS>
+      <SRS>EPSG:3109</SRS>
+      <SRS>EPSG:3110</SRS>
+      <SRS>EPSG:3111</SRS>
+      <SRS>EPSG:3112</SRS>
+      <SRS>EPSG:3113</SRS>
+      <SRS>EPSG:3114</SRS>
+      <SRS>EPSG:3115</SRS>
+      <SRS>EPSG:3116</SRS>
+      <SRS>EPSG:3117</SRS>
+      <SRS>EPSG:3118</SRS>
+      <SRS>EPSG:3119</SRS>
+      <SRS>EPSG:3120</SRS>
+      <SRS>EPSG:3121</SRS>
+      <SRS>EPSG:3122</SRS>
+      <SRS>EPSG:3123</SRS>
+      <SRS>EPSG:3124</SRS>
+      <SRS>EPSG:3125</SRS>
+      <SRS>EPSG:3126</SRS>
+      <SRS>EPSG:3127</SRS>
+      <SRS>EPSG:3128</SRS>
+      <SRS>EPSG:3129</SRS>
+      <SRS>EPSG:3130</SRS>
+      <SRS>EPSG:3131</SRS>
+      <SRS>EPSG:3132</SRS>
+      <SRS>EPSG:3133</SRS>
+      <SRS>EPSG:3134</SRS>
+      <SRS>EPSG:3135</SRS>
+      <SRS>EPSG:3136</SRS>
+      <SRS>EPSG:3137</SRS>
+      <SRS>EPSG:3138</SRS>
+      <SRS>EPSG:3139</SRS>
+      <SRS>EPSG:3140</SRS>
+      <SRS>EPSG:3141</SRS>
+      <SRS>EPSG:3142</SRS>
+      <SRS>EPSG:3143</SRS>
+      <SRS>EPSG:3144</SRS>
+      <SRS>EPSG:3145</SRS>
+      <SRS>EPSG:3146</SRS>
+      <SRS>EPSG:3147</SRS>
+      <SRS>EPSG:3148</SRS>
+      <SRS>EPSG:3149</SRS>
+      <SRS>EPSG:3150</SRS>
+      <SRS>EPSG:3151</SRS>
+      <SRS>EPSG:3152</SRS>
+      <SRS>EPSG:3153</SRS>
+      <SRS>EPSG:3154</SRS>
+      <SRS>EPSG:3155</SRS>
+      <SRS>EPSG:3156</SRS>
+      <SRS>EPSG:3157</SRS>
+      <SRS>EPSG:3158</SRS>
+      <SRS>EPSG:3159</SRS>
+      <SRS>EPSG:3160</SRS>
+      <SRS>EPSG:3161</SRS>
+      <SRS>EPSG:3162</SRS>
+      <SRS>EPSG:3163</SRS>
+      <SRS>EPSG:3164</SRS>
+      <SRS>EPSG:3165</SRS>
+      <SRS>EPSG:3166</SRS>
+      <SRS>EPSG:3167</SRS>
+      <SRS>EPSG:3168</SRS>
+      <SRS>EPSG:3169</SRS>
+      <SRS>EPSG:3170</SRS>
+      <SRS>EPSG:3171</SRS>
+      <SRS>EPSG:3172</SRS>
+      <SRS>EPSG:3173</SRS>
+      <SRS>EPSG:3174</SRS>
+      <SRS>EPSG:3175</SRS>
+      <SRS>EPSG:3176</SRS>
+      <SRS>EPSG:3177</SRS>
+      <SRS>EPSG:3178</SRS>
+      <SRS>EPSG:3179</SRS>
+      <SRS>EPSG:3180</SRS>
+      <SRS>EPSG:3181</SRS>
+      <SRS>EPSG:3182</SRS>
+      <SRS>EPSG:3183</SRS>
+      <SRS>EPSG:3184</SRS>
+      <SRS>EPSG:3185</SRS>
+      <SRS>EPSG:3186</SRS>
+      <SRS>EPSG:3187</SRS>
+      <SRS>EPSG:3188</SRS>
+      <SRS>EPSG:3189</SRS>
+      <SRS>EPSG:3190</SRS>
+      <SRS>EPSG:3191</SRS>
+      <SRS>EPSG:3192</SRS>
+      <SRS>EPSG:3193</SRS>
+      <SRS>EPSG:3194</SRS>
+      <SRS>EPSG:3195</SRS>
+      <SRS>EPSG:3196</SRS>
+      <SRS>EPSG:3197</SRS>
+      <SRS>EPSG:3198</SRS>
+      <SRS>EPSG:3199</SRS>
+      <SRS>EPSG:3200</SRS>
+      <SRS>EPSG:3201</SRS>
+      <SRS>EPSG:3202</SRS>
+      <SRS>EPSG:3203</SRS>
+      <SRS>EPSG:3204</SRS>
+      <SRS>EPSG:3205</SRS>
+      <SRS>EPSG:3206</SRS>
+      <SRS>EPSG:3207</SRS>
+      <SRS>EPSG:3208</SRS>
+      <SRS>EPSG:3209</SRS>
+      <SRS>EPSG:3210</SRS>
+      <SRS>EPSG:3211</SRS>
+      <SRS>EPSG:3212</SRS>
+      <SRS>EPSG:3213</SRS>
+      <SRS>EPSG:3214</SRS>
+      <SRS>EPSG:3215</SRS>
+      <SRS>EPSG:3216</SRS>
+      <SRS>EPSG:3217</SRS>
+      <SRS>EPSG:3218</SRS>
+      <SRS>EPSG:3219</SRS>
+      <SRS>EPSG:3220</SRS>
+      <SRS>EPSG:3221</SRS>
+      <SRS>EPSG:3222</SRS>
+      <SRS>EPSG:3223</SRS>
+      <SRS>EPSG:3224</SRS>
+      <SRS>EPSG:3225</SRS>
+      <SRS>EPSG:3226</SRS>
+      <SRS>EPSG:3227</SRS>
+      <SRS>EPSG:3228</SRS>
+      <SRS>EPSG:3229</SRS>
+      <SRS>EPSG:3230</SRS>
+      <SRS>EPSG:3231</SRS>
+      <SRS>EPSG:3232</SRS>
+      <SRS>EPSG:3233</SRS>
+      <SRS>EPSG:3234</SRS>
+      <SRS>EPSG:3235</SRS>
+      <SRS>EPSG:3236</SRS>
+      <SRS>EPSG:3237</SRS>
+      <SRS>EPSG:3238</SRS>
+      <SRS>EPSG:3239</SRS>
+      <SRS>EPSG:3240</SRS>
+      <SRS>EPSG:3241</SRS>
+      <SRS>EPSG:3242</SRS>
+      <SRS>EPSG:3243</SRS>
+      <SRS>EPSG:3244</SRS>
+      <SRS>EPSG:3245</SRS>
+      <SRS>EPSG:3246</SRS>
+      <SRS>EPSG:3247</SRS>
+      <SRS>EPSG:3248</SRS>
+      <SRS>EPSG:3249</SRS>
+      <SRS>EPSG:3250</SRS>
+      <SRS>EPSG:3251</SRS>
+      <SRS>EPSG:3252</SRS>
+      <SRS>EPSG:3253</SRS>
+      <SRS>EPSG:3254</SRS>
+      <SRS>EPSG:3255</SRS>
+      <SRS>EPSG:3256</SRS>
+      <SRS>EPSG:3257</SRS>
+      <SRS>EPSG:3258</SRS>
+      <SRS>EPSG:3259</SRS>
+      <SRS>EPSG:3260</SRS>
+      <SRS>EPSG:3261</SRS>
+      <SRS>EPSG:3262</SRS>
+      <SRS>EPSG:3263</SRS>
+      <SRS>EPSG:3264</SRS>
+      <SRS>EPSG:3265</SRS>
+      <SRS>EPSG:3266</SRS>
+      <SRS>EPSG:3267</SRS>
+      <SRS>EPSG:3268</SRS>
+      <SRS>EPSG:3269</SRS>
+      <SRS>EPSG:3270</SRS>
+      <SRS>EPSG:3271</SRS>
+      <SRS>EPSG:3272</SRS>
+      <SRS>EPSG:3273</SRS>
+      <SRS>EPSG:3274</SRS>
+      <SRS>EPSG:3275</SRS>
+      <SRS>EPSG:3276</SRS>
+      <SRS>EPSG:3277</SRS>
+      <SRS>EPSG:3278</SRS>
+      <SRS>EPSG:3279</SRS>
+      <SRS>EPSG:3280</SRS>
+      <SRS>EPSG:3281</SRS>
+      <SRS>EPSG:3282</SRS>
+      <SRS>EPSG:3283</SRS>
+      <SRS>EPSG:3284</SRS>
+      <SRS>EPSG:3285</SRS>
+      <SRS>EPSG:3286</SRS>
+      <SRS>EPSG:3287</SRS>
+      <SRS>EPSG:3288</SRS>
+      <SRS>EPSG:3289</SRS>
+      <SRS>EPSG:3290</SRS>
+      <SRS>EPSG:3291</SRS>
+      <SRS>EPSG:3292</SRS>
+      <SRS>EPSG:3293</SRS>
+      <SRS>EPSG:3294</SRS>
+      <SRS>EPSG:3295</SRS>
+      <SRS>EPSG:3296</SRS>
+      <SRS>EPSG:3297</SRS>
+      <SRS>EPSG:3298</SRS>
+      <SRS>EPSG:3299</SRS>
+      <SRS>EPSG:3300</SRS>
+      <SRS>EPSG:3301</SRS>
+      <SRS>EPSG:3302</SRS>
+      <SRS>EPSG:3303</SRS>
+      <SRS>EPSG:3304</SRS>
+      <SRS>EPSG:3305</SRS>
+      <SRS>EPSG:3306</SRS>
+      <SRS>EPSG:3307</SRS>
+      <SRS>EPSG:3308</SRS>
+      <SRS>EPSG:3309</SRS>
+      <SRS>EPSG:3310</SRS>
+      <SRS>EPSG:3311</SRS>
+      <SRS>EPSG:3312</SRS>
+      <SRS>EPSG:3313</SRS>
+      <SRS>EPSG:3314</SRS>
+      <SRS>EPSG:3315</SRS>
+      <SRS>EPSG:3316</SRS>
+      <SRS>EPSG:3317</SRS>
+      <SRS>EPSG:3318</SRS>
+      <SRS>EPSG:3319</SRS>
+      <SRS>EPSG:3320</SRS>
+      <SRS>EPSG:3321</SRS>
+      <SRS>EPSG:3322</SRS>
+      <SRS>EPSG:3323</SRS>
+      <SRS>EPSG:3324</SRS>
+      <SRS>EPSG:3325</SRS>
+      <SRS>EPSG:3326</SRS>
+      <SRS>EPSG:3327</SRS>
+      <SRS>EPSG:3328</SRS>
+      <SRS>EPSG:3329</SRS>
+      <SRS>EPSG:3330</SRS>
+      <SRS>EPSG:3331</SRS>
+      <SRS>EPSG:3332</SRS>
+      <SRS>EPSG:3333</SRS>
+      <SRS>EPSG:3334</SRS>
+      <SRS>EPSG:3335</SRS>
+      <SRS>EPSG:3336</SRS>
+      <SRS>EPSG:3337</SRS>
+      <SRS>EPSG:3338</SRS>
+      <SRS>EPSG:3339</SRS>
+      <SRS>EPSG:3340</SRS>
+      <SRS>EPSG:3341</SRS>
+      <SRS>EPSG:3342</SRS>
+      <SRS>EPSG:3343</SRS>
+      <SRS>EPSG:3344</SRS>
+      <SRS>EPSG:3345</SRS>
+      <SRS>EPSG:3346</SRS>
+      <SRS>EPSG:3347</SRS>
+      <SRS>EPSG:3348</SRS>
+      <SRS>EPSG:3349</SRS>
+      <SRS>EPSG:3350</SRS>
+      <SRS>EPSG:3351</SRS>
+      <SRS>EPSG:3352</SRS>
+      <SRS>EPSG:3353</SRS>
+      <SRS>EPSG:3354</SRS>
+      <SRS>EPSG:3355</SRS>
+      <SRS>EPSG:3356</SRS>
+      <SRS>EPSG:3357</SRS>
+      <SRS>EPSG:3358</SRS>
+      <SRS>EPSG:3359</SRS>
+      <SRS>EPSG:3360</SRS>
+      <SRS>EPSG:3361</SRS>
+      <SRS>EPSG:3362</SRS>
+      <SRS>EPSG:3363</SRS>
+      <SRS>EPSG:3364</SRS>
+      <SRS>EPSG:3365</SRS>
+      <SRS>EPSG:3366</SRS>
+      <SRS>EPSG:3367</SRS>
+      <SRS>EPSG:3368</SRS>
+      <SRS>EPSG:3369</SRS>
+      <SRS>EPSG:3370</SRS>
+      <SRS>EPSG:3371</SRS>
+      <SRS>EPSG:3372</SRS>
+      <SRS>EPSG:3373</SRS>
+      <SRS>EPSG:3374</SRS>
+      <SRS>EPSG:3375</SRS>
+      <SRS>EPSG:3376</SRS>
+      <SRS>EPSG:3377</SRS>
+      <SRS>EPSG:3378</SRS>
+      <SRS>EPSG:3379</SRS>
+      <SRS>EPSG:3380</SRS>
+      <SRS>EPSG:3381</SRS>
+      <SRS>EPSG:3382</SRS>
+      <SRS>EPSG:3383</SRS>
+      <SRS>EPSG:3384</SRS>
+      <SRS>EPSG:3385</SRS>
+      <SRS>EPSG:3386</SRS>
+      <SRS>EPSG:3387</SRS>
+      <SRS>EPSG:3388</SRS>
+      <SRS>EPSG:3389</SRS>
+      <SRS>EPSG:3390</SRS>
+      <SRS>EPSG:3391</SRS>
+      <SRS>EPSG:3392</SRS>
+      <SRS>EPSG:3393</SRS>
+      <SRS>EPSG:3394</SRS>
+      <SRS>EPSG:3395</SRS>
+      <SRS>EPSG:3396</SRS>
+      <SRS>EPSG:3397</SRS>
+      <SRS>EPSG:3398</SRS>
+      <SRS>EPSG:3399</SRS>
+      <SRS>EPSG:3400</SRS>
+      <SRS>EPSG:3401</SRS>
+      <SRS>EPSG:3402</SRS>
+      <SRS>EPSG:3403</SRS>
+      <SRS>EPSG:3404</SRS>
+      <SRS>EPSG:3405</SRS>
+      <SRS>EPSG:3406</SRS>
+      <SRS>EPSG:3407</SRS>
+      <SRS>EPSG:3408</SRS>
+      <SRS>EPSG:3409</SRS>
+      <SRS>EPSG:3410</SRS>
+      <SRS>EPSG:3411</SRS>
+      <SRS>EPSG:3412</SRS>
+      <SRS>EPSG:3413</SRS>
+      <SRS>EPSG:3414</SRS>
+      <SRS>EPSG:3415</SRS>
+      <SRS>EPSG:3416</SRS>
+      <SRS>EPSG:3417</SRS>
+      <SRS>EPSG:3418</SRS>
+      <SRS>EPSG:3419</SRS>
+      <SRS>EPSG:3420</SRS>
+      <SRS>EPSG:3421</SRS>
+      <SRS>EPSG:3422</SRS>
+      <SRS>EPSG:3423</SRS>
+      <SRS>EPSG:3424</SRS>
+      <SRS>EPSG:3425</SRS>
+      <SRS>EPSG:3426</SRS>
+      <SRS>EPSG:3427</SRS>
+      <SRS>EPSG:3428</SRS>
+      <SRS>EPSG:3429</SRS>
+      <SRS>EPSG:3430</SRS>
+      <SRS>EPSG:3431</SRS>
+      <SRS>EPSG:3432</SRS>
+      <SRS>EPSG:3433</SRS>
+      <SRS>EPSG:3434</SRS>
+      <SRS>EPSG:3435</SRS>
+      <SRS>EPSG:3436</SRS>
+      <SRS>EPSG:3437</SRS>
+      <SRS>EPSG:3438</SRS>
+      <SRS>EPSG:3439</SRS>
+      <SRS>EPSG:3440</SRS>
+      <SRS>EPSG:3441</SRS>
+      <SRS>EPSG:3442</SRS>
+      <SRS>EPSG:3443</SRS>
+      <SRS>EPSG:3444</SRS>
+      <SRS>EPSG:3445</SRS>
+      <SRS>EPSG:3446</SRS>
+      <SRS>EPSG:3447</SRS>
+      <SRS>EPSG:3448</SRS>
+      <SRS>EPSG:3449</SRS>
+      <SRS>EPSG:3450</SRS>
+      <SRS>EPSG:3451</SRS>
+      <SRS>EPSG:3452</SRS>
+      <SRS>EPSG:3453</SRS>
+      <SRS>EPSG:3454</SRS>
+      <SRS>EPSG:3455</SRS>
+      <SRS>EPSG:3456</SRS>
+      <SRS>EPSG:3457</SRS>
+      <SRS>EPSG:3458</SRS>
+      <SRS>EPSG:3459</SRS>
+      <SRS>EPSG:3460</SRS>
+      <SRS>EPSG:3461</SRS>
+      <SRS>EPSG:3462</SRS>
+      <SRS>EPSG:3463</SRS>
+      <SRS>EPSG:3464</SRS>
+      <SRS>EPSG:3560</SRS>
+      <SRS>EPSG:3561</SRS>
+      <SRS>EPSG:3562</SRS>
+      <SRS>EPSG:3563</SRS>
+      <SRS>EPSG:3564</SRS>
+      <SRS>EPSG:3565</SRS>
+      <SRS>EPSG:3566</SRS>
+      <SRS>EPSG:3567</SRS>
+      <SRS>EPSG:3568</SRS>
+      <SRS>EPSG:3569</SRS>
+      <SRS>EPSG:3570</SRS>
+      <SRS>EPSG:3571</SRS>
+      <SRS>EPSG:3572</SRS>
+      <SRS>EPSG:3573</SRS>
+      <SRS>EPSG:3574</SRS>
+      <SRS>EPSG:3575</SRS>
+      <SRS>EPSG:3576</SRS>
+      <SRS>EPSG:3577</SRS>
+      <SRS>EPSG:3920</SRS>
+      <SRS>EPSG:3991</SRS>
+      <SRS>EPSG:3992</SRS>
+      <SRS>EPSG:3993</SRS>
+      <SRS>EPSG:4001</SRS>
+      <SRS>EPSG:4002</SRS>
+      <SRS>EPSG:4003</SRS>
+      <SRS>EPSG:4004</SRS>
+      <SRS>EPSG:4005</SRS>
+      <SRS>EPSG:4006</SRS>
+      <SRS>EPSG:4007</SRS>
+      <SRS>EPSG:4008</SRS>
+      <SRS>EPSG:4009</SRS>
+      <SRS>EPSG:4010</SRS>
+      <SRS>EPSG:4011</SRS>
+      <SRS>EPSG:4012</SRS>
+      <SRS>EPSG:4013</SRS>
+      <SRS>EPSG:4014</SRS>
+      <SRS>EPSG:4015</SRS>
+      <SRS>EPSG:4016</SRS>
+      <SRS>EPSG:4018</SRS>
+      <SRS>EPSG:4019</SRS>
+      <SRS>EPSG:4020</SRS>
+      <SRS>EPSG:4021</SRS>
+      <SRS>EPSG:4022</SRS>
+      <SRS>EPSG:4024</SRS>
+      <SRS>EPSG:4025</SRS>
+      <SRS>EPSG:4027</SRS>
+      <SRS>EPSG:4028</SRS>
+      <SRS>EPSG:4029</SRS>
+      <SRS>EPSG:4030</SRS>
+      <SRS>EPSG:4031</SRS>
+      <SRS>EPSG:4032</SRS>
+      <SRS>EPSG:4033</SRS>
+      <SRS>EPSG:4034</SRS>
+      <SRS>EPSG:4035</SRS>
+      <SRS>EPSG:4036</SRS>
+      <SRS>EPSG:4041</SRS>
+      <SRS>EPSG:4042</SRS>
+      <SRS>EPSG:4043</SRS>
+      <SRS>EPSG:4044</SRS>
+      <SRS>EPSG:4045</SRS>
+      <SRS>EPSG:4047</SRS>
+      <SRS>EPSG:4052</SRS>
+      <SRS>EPSG:4053</SRS>
+      <SRS>EPSG:4054</SRS>
+      <SRS>EPSG:4120</SRS>
+      <SRS>EPSG:4121</SRS>
+      <SRS>EPSG:4122</SRS>
+      <SRS>EPSG:4123</SRS>
+      <SRS>EPSG:4124</SRS>
+      <SRS>EPSG:4125</SRS>
+      <SRS>EPSG:4126</SRS>
+      <SRS>EPSG:4127</SRS>
+      <SRS>EPSG:4128</SRS>
+      <SRS>EPSG:4129</SRS>
+      <SRS>EPSG:4130</SRS>
+      <SRS>EPSG:4131</SRS>
+      <SRS>EPSG:4132</SRS>
+      <SRS>EPSG:4133</SRS>
+      <SRS>EPSG:4134</SRS>
+      <SRS>EPSG:4135</SRS>
+      <SRS>EPSG:4136</SRS>
+      <SRS>EPSG:4137</SRS>
+      <SRS>EPSG:4138</SRS>
+      <SRS>EPSG:4139</SRS>
+      <SRS>EPSG:4140</SRS>
+      <SRS>EPSG:4141</SRS>
+      <SRS>EPSG:4142</SRS>
+      <SRS>EPSG:4143</SRS>
+      <SRS>EPSG:4144</SRS>
+      <SRS>EPSG:4145</SRS>
+      <SRS>EPSG:4146</SRS>
+      <SRS>EPSG:4147</SRS>
+      <SRS>EPSG:4148</SRS>
+      <SRS>EPSG:4149</SRS>
+      <SRS>EPSG:4150</SRS>
+      <SRS>EPSG:4151</SRS>
+      <SRS>EPSG:4152</SRS>
+      <SRS>EPSG:4153</SRS>
+      <SRS>EPSG:4154</SRS>
+      <SRS>EPSG:4155</SRS>
+      <SRS>EPSG:4156</SRS>
+      <SRS>EPSG:4157</SRS>
+      <SRS>EPSG:4158</SRS>
+      <SRS>EPSG:4159</SRS>
+      <SRS>EPSG:4160</SRS>
+      <SRS>EPSG:4161</SRS>
+      <SRS>EPSG:4162</SRS>
+      <SRS>EPSG:4163</SRS>
+      <SRS>EPSG:4164</SRS>
+      <SRS>EPSG:4165</SRS>
+      <SRS>EPSG:4166</SRS>
+      <SRS>EPSG:4167</SRS>
+      <SRS>EPSG:4168</SRS>
+      <SRS>EPSG:4169</SRS>
+      <SRS>EPSG:4170</SRS>
+      <SRS>EPSG:4171</SRS>
+      <SRS>EPSG:4172</SRS>
+      <SRS>EPSG:4173</SRS>
+      <SRS>EPSG:4174</SRS>
+      <SRS>EPSG:4175</SRS>
+      <SRS>EPSG:4176</SRS>
+      <SRS>EPSG:4178</SRS>
+      <SRS>EPSG:4179</SRS>
+      <SRS>EPSG:4180</SRS>
+      <SRS>EPSG:4181</SRS>
+      <SRS>EPSG:4182</SRS>
+      <SRS>EPSG:4183</SRS>
+      <SRS>EPSG:4184</SRS>
+      <SRS>EPSG:4185</SRS>
+      <SRS>EPSG:4188</SRS>
+      <SRS>EPSG:4189</SRS>
+      <SRS>EPSG:4190</SRS>
+      <SRS>EPSG:4191</SRS>
+      <SRS>EPSG:4192</SRS>
+      <SRS>EPSG:4193</SRS>
+      <SRS>EPSG:4194</SRS>
+      <SRS>EPSG:4195</SRS>
+      <SRS>EPSG:4196</SRS>
+      <SRS>EPSG:4197</SRS>
+      <SRS>EPSG:4198</SRS>
+      <SRS>EPSG:4199</SRS>
+      <SRS>EPSG:4200</SRS>
+      <SRS>EPSG:4201</SRS>
+      <SRS>EPSG:4202</SRS>
+      <SRS>EPSG:4203</SRS>
+      <SRS>EPSG:4204</SRS>
+      <SRS>EPSG:4205</SRS>
+      <SRS>EPSG:4206</SRS>
+      <SRS>EPSG:4207</SRS>
+      <SRS>EPSG:4208</SRS>
+      <SRS>EPSG:4209</SRS>
+      <SRS>EPSG:4210</SRS>
+      <SRS>EPSG:4211</SRS>
+      <SRS>EPSG:4212</SRS>
+      <SRS>EPSG:4213</SRS>
+      <SRS>EPSG:4214</SRS>
+      <SRS>EPSG:4215</SRS>
+      <SRS>EPSG:4216</SRS>
+      <SRS>EPSG:4218</SRS>
+      <SRS>EPSG:4219</SRS>
+      <SRS>EPSG:4220</SRS>
+      <SRS>EPSG:4221</SRS>
+      <SRS>EPSG:4222</SRS>
+      <SRS>EPSG:4223</SRS>
+      <SRS>EPSG:4224</SRS>
+      <SRS>EPSG:4225</SRS>
+      <SRS>EPSG:4226</SRS>
+      <SRS>EPSG:4227</SRS>
+      <SRS>EPSG:4228</SRS>
+      <SRS>EPSG:4229</SRS>
+      <SRS>EPSG:4230</SRS>
+      <SRS>EPSG:4231</SRS>
+      <SRS>EPSG:4232</SRS>
+      <SRS>EPSG:4233</SRS>
+      <SRS>EPSG:4234</SRS>
+      <SRS>EPSG:4235</SRS>
+      <SRS>EPSG:4236</SRS>
+      <SRS>EPSG:4237</SRS>
+      <SRS>EPSG:4238</SRS>
+      <SRS>EPSG:4239</SRS>
+      <SRS>EPSG:4240</SRS>
+      <SRS>EPSG:4241</SRS>
+      <SRS>EPSG:4242</SRS>
+      <SRS>EPSG:4243</SRS>
+      <SRS>EPSG:4244</SRS>
+      <SRS>EPSG:4245</SRS>
+      <SRS>EPSG:4246</SRS>
+      <SRS>EPSG:4247</SRS>
+      <SRS>EPSG:4248</SRS>
+      <SRS>EPSG:4249</SRS>
+      <SRS>EPSG:4250</SRS>
+      <SRS>EPSG:4251</SRS>
+      <SRS>EPSG:4252</SRS>
+      <SRS>EPSG:4253</SRS>
+      <SRS>EPSG:4254</SRS>
+      <SRS>EPSG:4255</SRS>
+      <SRS>EPSG:4256</SRS>
+      <SRS>EPSG:4257</SRS>
+      <SRS>EPSG:4258</SRS>
+      <SRS>EPSG:4259</SRS>
+      <SRS>EPSG:4260</SRS>
+      <SRS>EPSG:4261</SRS>
+      <SRS>EPSG:4262</SRS>
+      <SRS>EPSG:4263</SRS>
+      <SRS>EPSG:4264</SRS>
+      <SRS>EPSG:4265</SRS>
+      <SRS>EPSG:4266</SRS>
+      <SRS>EPSG:4267</SRS>
+      <SRS>EPSG:4268</SRS>
+      <SRS>EPSG:4269</SRS>
+      <SRS>EPSG:4270</SRS>
+      <SRS>EPSG:4271</SRS>
+      <SRS>EPSG:4272</SRS>
+      <SRS>EPSG:4273</SRS>
+      <SRS>EPSG:4274</SRS>
+      <SRS>EPSG:4275</SRS>
+      <SRS>EPSG:4276</SRS>
+      <SRS>EPSG:4277</SRS>
+      <SRS>EPSG:4278</SRS>
+      <SRS>EPSG:4279</SRS>
+      <SRS>EPSG:4280</SRS>
+      <SRS>EPSG:4281</SRS>
+      <SRS>EPSG:4282</SRS>
+      <SRS>EPSG:4283</SRS>
+      <SRS>EPSG:4284</SRS>
+      <SRS>EPSG:4285</SRS>
+      <SRS>EPSG:4286</SRS>
+      <SRS>EPSG:4287</SRS>
+      <SRS>EPSG:4288</SRS>
+      <SRS>EPSG:4289</SRS>
+      <SRS>EPSG:4291</SRS>
+      <SRS>EPSG:4292</SRS>
+      <SRS>EPSG:4293</SRS>
+      <SRS>EPSG:4294</SRS>
+      <SRS>EPSG:4295</SRS>
+      <SRS>EPSG:4296</SRS>
+      <SRS>EPSG:4297</SRS>
+      <SRS>EPSG:4298</SRS>
+      <SRS>EPSG:4299</SRS>
+      <SRS>EPSG:4300</SRS>
+      <SRS>EPSG:4301</SRS>
+      <SRS>EPSG:4302</SRS>
+      <SRS>EPSG:4303</SRS>
+      <SRS>EPSG:4304</SRS>
+      <SRS>EPSG:4306</SRS>
+      <SRS>EPSG:4307</SRS>
+      <SRS>EPSG:4308</SRS>
+      <SRS>EPSG:4309</SRS>
+      <SRS>EPSG:4310</SRS>
+      <SRS>EPSG:4311</SRS>
+      <SRS>EPSG:4312</SRS>
+      <SRS>EPSG:4313</SRS>
+      <SRS>EPSG:4314</SRS>
+      <SRS>EPSG:4315</SRS>
+      <SRS>EPSG:4316</SRS>
+      <SRS>EPSG:4317</SRS>
+      <SRS>EPSG:4318</SRS>
+      <SRS>EPSG:4319</SRS>
+      <SRS>EPSG:4322</SRS>
+      <SRS>EPSG:4324</SRS>
+      <SRS>EPSG:4326</SRS>
+      <SRS>EPSG:4327</SRS>
+      <SRS>EPSG:4328</SRS>
+      <SRS>EPSG:4329</SRS>
+      <SRS>EPSG:4330</SRS>
+      <SRS>EPSG:4331</SRS>
+      <SRS>EPSG:4332</SRS>
+      <SRS>EPSG:4333</SRS>
+      <SRS>EPSG:4334</SRS>
+      <SRS>EPSG:4335</SRS>
+      <SRS>EPSG:4336</SRS>
+      <SRS>EPSG:4337</SRS>
+      <SRS>EPSG:4338</SRS>
+      <SRS>EPSG:4339</SRS>
+      <SRS>EPSG:4340</SRS>
+      <SRS>EPSG:4341</SRS>
+      <SRS>EPSG:4342</SRS>
+      <SRS>EPSG:4343</SRS>
+      <SRS>EPSG:4344</SRS>
+      <SRS>EPSG:4345</SRS>
+      <SRS>EPSG:4346</SRS>
+      <SRS>EPSG:4347</SRS>
+      <SRS>EPSG:4348</SRS>
+      <SRS>EPSG:4349</SRS>
+      <SRS>EPSG:4350</SRS>
+      <SRS>EPSG:4351</SRS>
+      <SRS>EPSG:4352</SRS>
+      <SRS>EPSG:4353</SRS>
+      <SRS>EPSG:4354</SRS>
+      <SRS>EPSG:4355</SRS>
+      <SRS>EPSG:4356</SRS>
+      <SRS>EPSG:4357</SRS>
+      <SRS>EPSG:4358</SRS>
+      <SRS>EPSG:4359</SRS>
+      <SRS>EPSG:4360</SRS>
+      <SRS>EPSG:4361</SRS>
+      <SRS>EPSG:4362</SRS>
+      <SRS>EPSG:4363</SRS>
+      <SRS>EPSG:4364</SRS>
+      <SRS>EPSG:4365</SRS>
+      <SRS>EPSG:4366</SRS>
+      <SRS>EPSG:4367</SRS>
+      <SRS>EPSG:4368</SRS>
+      <SRS>EPSG:4369</SRS>
+      <SRS>EPSG:4370</SRS>
+      <SRS>EPSG:4371</SRS>
+      <SRS>EPSG:4372</SRS>
+      <SRS>EPSG:4373</SRS>
+      <SRS>EPSG:4374</SRS>
+      <SRS>EPSG:4375</SRS>
+      <SRS>EPSG:4376</SRS>
+      <SRS>EPSG:4377</SRS>
+      <SRS>EPSG:4378</SRS>
+      <SRS>EPSG:4379</SRS>
+      <SRS>EPSG:4380</SRS>
+      <SRS>EPSG:4381</SRS>
+      <SRS>EPSG:4382</SRS>
+      <SRS>EPSG:4383</SRS>
+      <SRS>EPSG:4384</SRS>
+      <SRS>EPSG:4385</SRS>
+      <SRS>EPSG:4386</SRS>
+      <SRS>EPSG:4387</SRS>
+      <SRS>EPSG:4388</SRS>
+      <SRS>EPSG:4389</SRS>
+      <SRS>EPSG:4600</SRS>
+      <SRS>EPSG:4601</SRS>
+      <SRS>EPSG:4602</SRS>
+      <SRS>EPSG:4603</SRS>
+      <SRS>EPSG:4604</SRS>
+      <SRS>EPSG:4605</SRS>
+      <SRS>EPSG:4606</SRS>
+      <SRS>EPSG:4607</SRS>
+      <SRS>EPSG:4608</SRS>
+      <SRS>EPSG:4609</SRS>
+      <SRS>EPSG:4610</SRS>
+      <SRS>EPSG:4611</SRS>
+      <SRS>EPSG:4612</SRS>
+      <SRS>EPSG:4613</SRS>
+      <SRS>EPSG:4614</SRS>
+      <SRS>EPSG:4615</SRS>
+      <SRS>EPSG:4616</SRS>
+      <SRS>EPSG:4617</SRS>
+      <SRS>EPSG:4618</SRS>
+      <SRS>EPSG:4619</SRS>
+      <SRS>EPSG:4620</SRS>
+      <SRS>EPSG:4621</SRS>
+      <SRS>EPSG:4622</SRS>
+      <SRS>EPSG:4623</SRS>
+      <SRS>EPSG:4624</SRS>
+      <SRS>EPSG:4625</SRS>
+      <SRS>EPSG:4626</SRS>
+      <SRS>EPSG:4627</SRS>
+      <SRS>EPSG:4628</SRS>
+      <SRS>EPSG:4629</SRS>
+      <SRS>EPSG:4630</SRS>
+      <SRS>EPSG:4631</SRS>
+      <SRS>EPSG:4632</SRS>
+      <SRS>EPSG:4633</SRS>
+      <SRS>EPSG:4634</SRS>
+      <SRS>EPSG:4635</SRS>
+      <SRS>EPSG:4636</SRS>
+      <SRS>EPSG:4637</SRS>
+      <SRS>EPSG:4638</SRS>
+      <SRS>EPSG:4639</SRS>
+      <SRS>EPSG:4640</SRS>
+      <SRS>EPSG:4641</SRS>
+      <SRS>EPSG:4642</SRS>
+      <SRS>EPSG:4643</SRS>
+      <SRS>EPSG:4644</SRS>
+      <SRS>EPSG:4645</SRS>
+      <SRS>EPSG:4646</SRS>
+      <SRS>EPSG:4657</SRS>
+      <SRS>EPSG:4658</SRS>
+      <SRS>EPSG:4659</SRS>
+      <SRS>EPSG:4660</SRS>
+      <SRS>EPSG:4661</SRS>
+      <SRS>EPSG:4662</SRS>
+      <SRS>EPSG:4663</SRS>
+      <SRS>EPSG:4664</SRS>
+      <SRS>EPSG:4665</SRS>
+      <SRS>EPSG:4666</SRS>
+      <SRS>EPSG:4667</SRS>
+      <SRS>EPSG:4668</SRS>
+      <SRS>EPSG:4669</SRS>
+      <SRS>EPSG:4670</SRS>
+      <SRS>EPSG:4671</SRS>
+      <SRS>EPSG:4672</SRS>
+      <SRS>EPSG:4673</SRS>
+      <SRS>EPSG:4674</SRS>
+      <SRS>EPSG:4675</SRS>
+      <SRS>EPSG:4676</SRS>
+      <SRS>EPSG:4677</SRS>
+      <SRS>EPSG:4678</SRS>
+      <SRS>EPSG:4679</SRS>
+      <SRS>EPSG:4680</SRS>
+      <SRS>EPSG:4681</SRS>
+      <SRS>EPSG:4682</SRS>
+      <SRS>EPSG:4683</SRS>
+      <SRS>EPSG:4684</SRS>
+      <SRS>EPSG:4685</SRS>
+      <SRS>EPSG:4686</SRS>
+      <SRS>EPSG:4687</SRS>
+      <SRS>EPSG:4688</SRS>
+      <SRS>EPSG:4689</SRS>
+      <SRS>EPSG:4690</SRS>
+      <SRS>EPSG:4691</SRS>
+      <SRS>EPSG:4692</SRS>
+      <SRS>EPSG:4693</SRS>
+      <SRS>EPSG:4694</SRS>
+      <SRS>EPSG:4695</SRS>
+      <SRS>EPSG:4696</SRS>
+      <SRS>EPSG:4697</SRS>
+      <SRS>EPSG:4698</SRS>
+      <SRS>EPSG:4699</SRS>
+      <SRS>EPSG:4700</SRS>
+      <SRS>EPSG:4701</SRS>
+      <SRS>EPSG:4702</SRS>
+      <SRS>EPSG:4703</SRS>
+      <SRS>EPSG:4704</SRS>
+      <SRS>EPSG:4705</SRS>
+      <SRS>EPSG:4706</SRS>
+      <SRS>EPSG:4707</SRS>
+      <SRS>EPSG:4708</SRS>
+      <SRS>EPSG:4709</SRS>
+      <SRS>EPSG:4710</SRS>
+      <SRS>EPSG:4711</SRS>
+      <SRS>EPSG:4712</SRS>
+      <SRS>EPSG:4713</SRS>
+      <SRS>EPSG:4714</SRS>
+      <SRS>EPSG:4715</SRS>
+      <SRS>EPSG:4716</SRS>
+      <SRS>EPSG:4717</SRS>
+      <SRS>EPSG:4718</SRS>
+      <SRS>EPSG:4719</SRS>
+      <SRS>EPSG:4720</SRS>
+      <SRS>EPSG:4721</SRS>
+      <SRS>EPSG:4722</SRS>
+      <SRS>EPSG:4723</SRS>
+      <SRS>EPSG:4724</SRS>
+      <SRS>EPSG:4725</SRS>
+      <SRS>EPSG:4726</SRS>
+      <SRS>EPSG:4727</SRS>
+      <SRS>EPSG:4728</SRS>
+      <SRS>EPSG:4729</SRS>
+      <SRS>EPSG:4730</SRS>
+      <SRS>EPSG:4731</SRS>
+      <SRS>EPSG:4732</SRS>
+      <SRS>EPSG:4733</SRS>
+      <SRS>EPSG:4734</SRS>
+      <SRS>EPSG:4735</SRS>
+      <SRS>EPSG:4736</SRS>
+      <SRS>EPSG:4737</SRS>
+      <SRS>EPSG:4738</SRS>
+      <SRS>EPSG:4739</SRS>
+      <SRS>EPSG:4740</SRS>
+      <SRS>EPSG:4741</SRS>
+      <SRS>EPSG:4742</SRS>
+      <SRS>EPSG:4743</SRS>
+      <SRS>EPSG:4744</SRS>
+      <SRS>EPSG:4745</SRS>
+      <SRS>EPSG:4746</SRS>
+      <SRS>EPSG:4747</SRS>
+      <SRS>EPSG:4748</SRS>
+      <SRS>EPSG:4749</SRS>
+      <SRS>EPSG:4750</SRS>
+      <SRS>EPSG:4751</SRS>
+      <SRS>EPSG:4752</SRS>
+      <SRS>EPSG:4753</SRS>
+      <SRS>EPSG:4754</SRS>
+      <SRS>EPSG:4755</SRS>
+      <SRS>EPSG:4756</SRS>
+      <SRS>EPSG:4757</SRS>
+      <SRS>EPSG:4758</SRS>
+      <SRS>EPSG:4801</SRS>
+      <SRS>EPSG:4802</SRS>
+      <SRS>EPSG:4803</SRS>
+      <SRS>EPSG:4804</SRS>
+      <SRS>EPSG:4805</SRS>
+      <SRS>EPSG:4806</SRS>
+      <SRS>EPSG:4807</SRS>
+      <SRS>EPSG:4808</SRS>
+      <SRS>EPSG:4809</SRS>
+      <SRS>EPSG:4810</SRS>
+      <SRS>EPSG:4811</SRS>
+      <SRS>EPSG:4813</SRS>
+      <SRS>EPSG:4814</SRS>
+      <SRS>EPSG:4815</SRS>
+      <SRS>EPSG:4816</SRS>
+      <SRS>EPSG:4817</SRS>
+      <SRS>EPSG:4818</SRS>
+      <SRS>EPSG:4819</SRS>
+      <SRS>EPSG:4820</SRS>
+      <SRS>EPSG:4821</SRS>
+      <SRS>EPSG:4894</SRS>
+      <SRS>EPSG:4895</SRS>
+      <SRS>EPSG:4896</SRS>
+      <SRS>EPSG:4897</SRS>
+      <SRS>EPSG:4898</SRS>
+      <SRS>EPSG:4899</SRS>
+      <SRS>EPSG:4900</SRS>
+      <SRS>EPSG:4901</SRS>
+      <SRS>EPSG:4902</SRS>
+      <SRS>EPSG:4903</SRS>
+      <SRS>EPSG:4904</SRS>
+      <SRS>EPSG:4906</SRS>
+      <SRS>EPSG:4907</SRS>
+      <SRS>EPSG:4908</SRS>
+      <SRS>EPSG:4909</SRS>
+      <SRS>EPSG:4910</SRS>
+      <SRS>EPSG:4911</SRS>
+      <SRS>EPSG:4912</SRS>
+      <SRS>EPSG:4913</SRS>
+      <SRS>EPSG:4914</SRS>
+      <SRS>EPSG:4915</SRS>
+      <SRS>EPSG:4916</SRS>
+      <SRS>EPSG:4917</SRS>
+      <SRS>EPSG:4918</SRS>
+      <SRS>EPSG:4919</SRS>
+      <SRS>EPSG:4920</SRS>
+      <SRS>EPSG:4921</SRS>
+      <SRS>EPSG:4922</SRS>
+      <SRS>EPSG:4923</SRS>
+      <SRS>EPSG:4924</SRS>
+      <SRS>EPSG:4925</SRS>
+      <SRS>EPSG:4926</SRS>
+      <SRS>EPSG:4927</SRS>
+      <SRS>EPSG:4928</SRS>
+      <SRS>EPSG:4929</SRS>
+      <SRS>EPSG:4930</SRS>
+      <SRS>EPSG:4931</SRS>
+      <SRS>EPSG:4932</SRS>
+      <SRS>EPSG:4933</SRS>
+      <SRS>EPSG:4934</SRS>
+      <SRS>EPSG:4935</SRS>
+      <SRS>EPSG:4936</SRS>
+      <SRS>EPSG:4937</SRS>
+      <SRS>EPSG:4938</SRS>
+      <SRS>EPSG:4939</SRS>
+      <SRS>EPSG:4940</SRS>
+      <SRS>EPSG:4941</SRS>
+      <SRS>EPSG:4942</SRS>
+      <SRS>EPSG:4943</SRS>
+      <SRS>EPSG:4944</SRS>
+      <SRS>EPSG:4945</SRS>
+      <SRS>EPSG:4946</SRS>
+      <SRS>EPSG:4947</SRS>
+      <SRS>EPSG:4948</SRS>
+      <SRS>EPSG:4949</SRS>
+      <SRS>EPSG:4950</SRS>
+      <SRS>EPSG:4951</SRS>
+      <SRS>EPSG:4952</SRS>
+      <SRS>EPSG:4953</SRS>
+      <SRS>EPSG:4954</SRS>
+      <SRS>EPSG:4955</SRS>
+      <SRS>EPSG:4956</SRS>
+      <SRS>EPSG:4957</SRS>
+      <SRS>EPSG:4958</SRS>
+      <SRS>EPSG:4959</SRS>
+      <SRS>EPSG:4960</SRS>
+      <SRS>EPSG:4961</SRS>
+      <SRS>EPSG:4962</SRS>
+      <SRS>EPSG:4963</SRS>
+      <SRS>EPSG:4964</SRS>
+      <SRS>EPSG:4965</SRS>
+      <SRS>EPSG:4966</SRS>
+      <SRS>EPSG:4967</SRS>
+      <SRS>EPSG:4968</SRS>
+      <SRS>EPSG:4969</SRS>
+      <SRS>EPSG:4970</SRS>
+      <SRS>EPSG:4971</SRS>
+      <SRS>EPSG:4972</SRS>
+      <SRS>EPSG:4973</SRS>
+      <SRS>EPSG:4974</SRS>
+      <SRS>EPSG:4975</SRS>
+      <SRS>EPSG:4976</SRS>
+      <SRS>EPSG:4977</SRS>
+      <SRS>EPSG:4978</SRS>
+      <SRS>EPSG:4979</SRS>
+      <SRS>EPSG:4980</SRS>
+      <SRS>EPSG:4981</SRS>
+      <SRS>EPSG:4982</SRS>
+      <SRS>EPSG:4983</SRS>
+      <SRS>EPSG:4984</SRS>
+      <SRS>EPSG:4985</SRS>
+      <SRS>EPSG:4986</SRS>
+      <SRS>EPSG:4987</SRS>
+      <SRS>EPSG:4988</SRS>
+      <SRS>EPSG:4989</SRS>
+      <SRS>EPSG:4990</SRS>
+      <SRS>EPSG:4991</SRS>
+      <SRS>EPSG:4992</SRS>
+      <SRS>EPSG:4993</SRS>
+      <SRS>EPSG:4994</SRS>
+      <SRS>EPSG:4995</SRS>
+      <SRS>EPSG:4996</SRS>
+      <SRS>EPSG:4997</SRS>
+      <SRS>EPSG:4998</SRS>
+      <SRS>EPSG:4999</SRS>
+      <SRS>EPSG:5600</SRS>
+      <SRS>EPSG:5601</SRS>
+      <SRS>EPSG:5602</SRS>
+      <SRS>EPSG:5603</SRS>
+      <SRS>EPSG:5604</SRS>
+      <SRS>EPSG:5605</SRS>
+      <SRS>EPSG:5606</SRS>
+      <SRS>EPSG:5607</SRS>
+      <SRS>EPSG:5608</SRS>
+      <SRS>EPSG:5609</SRS>
+      <SRS>EPSG:5701</SRS>
+      <SRS>EPSG:5702</SRS>
+      <SRS>EPSG:5703</SRS>
+      <SRS>EPSG:5704</SRS>
+      <SRS>EPSG:5705</SRS>
+      <SRS>EPSG:5706</SRS>
+      <SRS>EPSG:5709</SRS>
+      <SRS>EPSG:5710</SRS>
+      <SRS>EPSG:5711</SRS>
+      <SRS>EPSG:5712</SRS>
+      <SRS>EPSG:5713</SRS>
+      <SRS>EPSG:5714</SRS>
+      <SRS>EPSG:5715</SRS>
+      <SRS>EPSG:5716</SRS>
+      <SRS>EPSG:5717</SRS>
+      <SRS>EPSG:5718</SRS>
+      <SRS>EPSG:5719</SRS>
+      <SRS>EPSG:5720</SRS>
+      <SRS>EPSG:5721</SRS>
+      <SRS>EPSG:5722</SRS>
+      <SRS>EPSG:5723</SRS>
+      <SRS>EPSG:5724</SRS>
+      <SRS>EPSG:5725</SRS>
+      <SRS>EPSG:5726</SRS>
+      <SRS>EPSG:5727</SRS>
+      <SRS>EPSG:5728</SRS>
+      <SRS>EPSG:5729</SRS>
+      <SRS>EPSG:5730</SRS>
+      <SRS>EPSG:5731</SRS>
+      <SRS>EPSG:5732</SRS>
+      <SRS>EPSG:5733</SRS>
+      <SRS>EPSG:5734</SRS>
+      <SRS>EPSG:5735</SRS>
+      <SRS>EPSG:5736</SRS>
+      <SRS>EPSG:5737</SRS>
+      <SRS>EPSG:5738</SRS>
+      <SRS>EPSG:5739</SRS>
+      <SRS>EPSG:5740</SRS>
+      <SRS>EPSG:5741</SRS>
+      <SRS>EPSG:5742</SRS>
+      <SRS>EPSG:5743</SRS>
+      <SRS>EPSG:5744</SRS>
+      <SRS>EPSG:5745</SRS>
+      <SRS>EPSG:5746</SRS>
+      <SRS>EPSG:5747</SRS>
+      <SRS>EPSG:5748</SRS>
+      <SRS>EPSG:5749</SRS>
+      <SRS>EPSG:5750</SRS>
+      <SRS>EPSG:5751</SRS>
+      <SRS>EPSG:5752</SRS>
+      <SRS>EPSG:5753</SRS>
+      <SRS>EPSG:5754</SRS>
+      <SRS>EPSG:5755</SRS>
+      <SRS>EPSG:5756</SRS>
+      <SRS>EPSG:5757</SRS>
+      <SRS>EPSG:5758</SRS>
+      <SRS>EPSG:5759</SRS>
+      <SRS>EPSG:5760</SRS>
+      <SRS>EPSG:5761</SRS>
+      <SRS>EPSG:5762</SRS>
+      <SRS>EPSG:5763</SRS>
+      <SRS>EPSG:5764</SRS>
+      <SRS>EPSG:5765</SRS>
+      <SRS>EPSG:5766</SRS>
+      <SRS>EPSG:5767</SRS>
+      <SRS>EPSG:5768</SRS>
+      <SRS>EPSG:5769</SRS>
+      <SRS>EPSG:5770</SRS>
+      <SRS>EPSG:5771</SRS>
+      <SRS>EPSG:5772</SRS>
+      <SRS>EPSG:5773</SRS>
+      <SRS>EPSG:5774</SRS>
+      <SRS>EPSG:5775</SRS>
+      <SRS>EPSG:5776</SRS>
+      <SRS>EPSG:5777</SRS>
+      <SRS>EPSG:5778</SRS>
+      <SRS>EPSG:5779</SRS>
+      <SRS>EPSG:5780</SRS>
+      <SRS>EPSG:5781</SRS>
+      <SRS>EPSG:5782</SRS>
+      <SRS>EPSG:5783</SRS>
+      <SRS>EPSG:5784</SRS>
+      <SRS>EPSG:5785</SRS>
+      <SRS>EPSG:5786</SRS>
+      <SRS>EPSG:5787</SRS>
+      <SRS>EPSG:5788</SRS>
+      <SRS>EPSG:5789</SRS>
+      <SRS>EPSG:5790</SRS>
+      <SRS>EPSG:5791</SRS>
+      <SRS>EPSG:5792</SRS>
+      <SRS>EPSG:5793</SRS>
+      <SRS>EPSG:5794</SRS>
+      <SRS>EPSG:5795</SRS>
+      <SRS>EPSG:5796</SRS>
+      <SRS>EPSG:5797</SRS>
+      <SRS>EPSG:5798</SRS>
+      <SRS>EPSG:5799</SRS>
+      <SRS>EPSG:5800</SRS>
+      <SRS>EPSG:5801</SRS>
+      <SRS>EPSG:5802</SRS>
+      <SRS>EPSG:5803</SRS>
+      <SRS>EPSG:5804</SRS>
+      <SRS>EPSG:5805</SRS>
+      <SRS>EPSG:5806</SRS>
+      <SRS>EPSG:5807</SRS>
+      <SRS>EPSG:5808</SRS>
+      <SRS>EPSG:5809</SRS>
+      <SRS>EPSG:5810</SRS>
+      <SRS>EPSG:5811</SRS>
+      <SRS>EPSG:5812</SRS>
+      <SRS>EPSG:5813</SRS>
+      <SRS>EPSG:5814</SRS>
+      <SRS>EPSG:5815</SRS>
+      <SRS>EPSG:5816</SRS>
+      <SRS>EPSG:5817</SRS>
+      <SRS>EPSG:5818</SRS>
+      <SRS>EPSG:7400</SRS>
+      <SRS>EPSG:7401</SRS>
+      <SRS>EPSG:7402</SRS>
+      <SRS>EPSG:7403</SRS>
+      <SRS>EPSG:7404</SRS>
+      <SRS>EPSG:7405</SRS>
+      <SRS>EPSG:7406</SRS>
+      <SRS>EPSG:7407</SRS>
+      <SRS>EPSG:7408</SRS>
+      <SRS>EPSG:7409</SRS>
+      <SRS>EPSG:7410</SRS>
+      <SRS>EPSG:7411</SRS>
+      <SRS>EPSG:7412</SRS>
+      <SRS>EPSG:7413</SRS>
+      <SRS>EPSG:7414</SRS>
+      <SRS>EPSG:7415</SRS>
+      <SRS>EPSG:7416</SRS>
+      <SRS>EPSG:7417</SRS>
+      <SRS>EPSG:7418</SRS>
+      <SRS>EPSG:7419</SRS>
+      <SRS>EPSG:7420</SRS>
+      <SRS>EPSG:20004</SRS>
+      <SRS>EPSG:20005</SRS>
+      <SRS>EPSG:20006</SRS>
+      <SRS>EPSG:20007</SRS>
+      <SRS>EPSG:20008</SRS>
+      <SRS>EPSG:20009</SRS>
+      <SRS>EPSG:20010</SRS>
+      <SRS>EPSG:20011</SRS>
+      <SRS>EPSG:20012</SRS>
+      <SRS>EPSG:20013</SRS>
+      <SRS>EPSG:20014</SRS>
+      <SRS>EPSG:20015</SRS>
+      <SRS>EPSG:20016</SRS>
+      <SRS>EPSG:20017</SRS>
+      <SRS>EPSG:20018</SRS>
+      <SRS>EPSG:20019</SRS>
+      <SRS>EPSG:20020</SRS>
+      <SRS>EPSG:20021</SRS>
+      <SRS>EPSG:20022</SRS>
+      <SRS>EPSG:20023</SRS>
+      <SRS>EPSG:20024</SRS>
+      <SRS>EPSG:20025</SRS>
+      <SRS>EPSG:20026</SRS>
+      <SRS>EPSG:20027</SRS>
+      <SRS>EPSG:20028</SRS>
+      <SRS>EPSG:20029</SRS>
+      <SRS>EPSG:20030</SRS>
+      <SRS>EPSG:20031</SRS>
+      <SRS>EPSG:20032</SRS>
+      <SRS>EPSG:20064</SRS>
+      <SRS>EPSG:20065</SRS>
+      <SRS>EPSG:20066</SRS>
+      <SRS>EPSG:20067</SRS>
+      <SRS>EPSG:20068</SRS>
+      <SRS>EPSG:20069</SRS>
+      <SRS>EPSG:20070</SRS>
+      <SRS>EPSG:20071</SRS>
+      <SRS>EPSG:20072</SRS>
+      <SRS>EPSG:20073</SRS>
+      <SRS>EPSG:20074</SRS>
+      <SRS>EPSG:20075</SRS>
+      <SRS>EPSG:20076</SRS>
+      <SRS>EPSG:20077</SRS>
+      <SRS>EPSG:20078</SRS>
+      <SRS>EPSG:20079</SRS>
+      <SRS>EPSG:20080</SRS>
+      <SRS>EPSG:20081</SRS>
+      <SRS>EPSG:20082</SRS>
+      <SRS>EPSG:20083</SRS>
+      <SRS>EPSG:20084</SRS>
+      <SRS>EPSG:20085</SRS>
+      <SRS>EPSG:20086</SRS>
+      <SRS>EPSG:20087</SRS>
+      <SRS>EPSG:20088</SRS>
+      <SRS>EPSG:20089</SRS>
+      <SRS>EPSG:20090</SRS>
+      <SRS>EPSG:20091</SRS>
+      <SRS>EPSG:20092</SRS>
+      <SRS>EPSG:20135</SRS>
+      <SRS>EPSG:20136</SRS>
+      <SRS>EPSG:20137</SRS>
+      <SRS>EPSG:20138</SRS>
+      <SRS>EPSG:20248</SRS>
+      <SRS>EPSG:20249</SRS>
+      <SRS>EPSG:20250</SRS>
+      <SRS>EPSG:20251</SRS>
+      <SRS>EPSG:20252</SRS>
+      <SRS>EPSG:20253</SRS>
+      <SRS>EPSG:20254</SRS>
+      <SRS>EPSG:20255</SRS>
+      <SRS>EPSG:20256</SRS>
+      <SRS>EPSG:20257</SRS>
+      <SRS>EPSG:20258</SRS>
+      <SRS>EPSG:20348</SRS>
+      <SRS>EPSG:20349</SRS>
+      <SRS>EPSG:20350</SRS>
+      <SRS>EPSG:20351</SRS>
+      <SRS>EPSG:20352</SRS>
+      <SRS>EPSG:20353</SRS>
+      <SRS>EPSG:20354</SRS>
+      <SRS>EPSG:20355</SRS>
+      <SRS>EPSG:20356</SRS>
+      <SRS>EPSG:20357</SRS>
+      <SRS>EPSG:20358</SRS>
+      <SRS>EPSG:20436</SRS>
+      <SRS>EPSG:20437</SRS>
+      <SRS>EPSG:20438</SRS>
+      <SRS>EPSG:20439</SRS>
+      <SRS>EPSG:20440</SRS>
+      <SRS>EPSG:20499</SRS>
+      <SRS>EPSG:20538</SRS>
+      <SRS>EPSG:20539</SRS>
+      <SRS>EPSG:20790</SRS>
+      <SRS>EPSG:20791</SRS>
+      <SRS>EPSG:20822</SRS>
+      <SRS>EPSG:20823</SRS>
+      <SRS>EPSG:20824</SRS>
+      <SRS>EPSG:20934</SRS>
+      <SRS>EPSG:20935</SRS>
+      <SRS>EPSG:20936</SRS>
+      <SRS>EPSG:21035</SRS>
+      <SRS>EPSG:21036</SRS>
+      <SRS>EPSG:21037</SRS>
+      <SRS>EPSG:21095</SRS>
+      <SRS>EPSG:21096</SRS>
+      <SRS>EPSG:21097</SRS>
+      <SRS>EPSG:21100</SRS>
+      <SRS>EPSG:21148</SRS>
+      <SRS>EPSG:21149</SRS>
+      <SRS>EPSG:21150</SRS>
+      <SRS>EPSG:21291</SRS>
+      <SRS>EPSG:21292</SRS>
+      <SRS>EPSG:21413</SRS>
+      <SRS>EPSG:21414</SRS>
+      <SRS>EPSG:21415</SRS>
+      <SRS>EPSG:21416</SRS>
+      <SRS>EPSG:21417</SRS>
+      <SRS>EPSG:21418</SRS>
+      <SRS>EPSG:21419</SRS>
+      <SRS>EPSG:21420</SRS>
+      <SRS>EPSG:21421</SRS>
+      <SRS>EPSG:21422</SRS>
+      <SRS>EPSG:21423</SRS>
+      <SRS>EPSG:21453</SRS>
+      <SRS>EPSG:21454</SRS>
+      <SRS>EPSG:21455</SRS>
+      <SRS>EPSG:21456</SRS>
+      <SRS>EPSG:21457</SRS>
+      <SRS>EPSG:21458</SRS>
+      <SRS>EPSG:21459</SRS>
+      <SRS>EPSG:21460</SRS>
+      <SRS>EPSG:21461</SRS>
+      <SRS>EPSG:21462</SRS>
+      <SRS>EPSG:21463</SRS>
+      <SRS>EPSG:21473</SRS>
+      <SRS>EPSG:21474</SRS>
+      <SRS>EPSG:21475</SRS>
+      <SRS>EPSG:21476</SRS>
+      <SRS>EPSG:21477</SRS>
+      <SRS>EPSG:21478</SRS>
+      <SRS>EPSG:21479</SRS>
+      <SRS>EPSG:21480</SRS>
+      <SRS>EPSG:21481</SRS>
+      <SRS>EPSG:21482</SRS>
+      <SRS>EPSG:21483</SRS>
+      <SRS>EPSG:21500</SRS>
+      <SRS>EPSG:21780</SRS>
+      <SRS>EPSG:21781</SRS>
+      <SRS>EPSG:21817</SRS>
+      <SRS>EPSG:21818</SRS>
+      <SRS>EPSG:21891</SRS>
+      <SRS>EPSG:21892</SRS>
+      <SRS>EPSG:21893</SRS>
+      <SRS>EPSG:21894</SRS>
+      <SRS>EPSG:21896</SRS>
+      <SRS>EPSG:21897</SRS>
+      <SRS>EPSG:21898</SRS>
+      <SRS>EPSG:21899</SRS>
+      <SRS>EPSG:22032</SRS>
+      <SRS>EPSG:22033</SRS>
+      <SRS>EPSG:22091</SRS>
+      <SRS>EPSG:22092</SRS>
+      <SRS>EPSG:22171</SRS>
+      <SRS>EPSG:22172</SRS>
+      <SRS>EPSG:22173</SRS>
+      <SRS>EPSG:22174</SRS>
+      <SRS>EPSG:22175</SRS>
+      <SRS>EPSG:22176</SRS>
+      <SRS>EPSG:22177</SRS>
+      <SRS>EPSG:22181</SRS>
+      <SRS>EPSG:22182</SRS>
+      <SRS>EPSG:22183</SRS>
+      <SRS>EPSG:22184</SRS>
+      <SRS>EPSG:22185</SRS>
+      <SRS>EPSG:22186</SRS>
+      <SRS>EPSG:22187</SRS>
+      <SRS>EPSG:22191</SRS>
+      <SRS>EPSG:22192</SRS>
+      <SRS>EPSG:22193</SRS>
+      <SRS>EPSG:22194</SRS>
+      <SRS>EPSG:22195</SRS>
+      <SRS>EPSG:22196</SRS>
+      <SRS>EPSG:22197</SRS>
+      <SRS>EPSG:22234</SRS>
+      <SRS>EPSG:22235</SRS>
+      <SRS>EPSG:22236</SRS>
+      <SRS>EPSG:22275</SRS>
+      <SRS>EPSG:22277</SRS>
+      <SRS>EPSG:22279</SRS>
+      <SRS>EPSG:22281</SRS>
+      <SRS>EPSG:22283</SRS>
+      <SRS>EPSG:22285</SRS>
+      <SRS>EPSG:22287</SRS>
+      <SRS>EPSG:22289</SRS>
+      <SRS>EPSG:22291</SRS>
+      <SRS>EPSG:22293</SRS>
+      <SRS>EPSG:22300</SRS>
+      <SRS>EPSG:22332</SRS>
+      <SRS>EPSG:22391</SRS>
+      <SRS>EPSG:22392</SRS>
+      <SRS>EPSG:22521</SRS>
+      <SRS>EPSG:22522</SRS>
+      <SRS>EPSG:22523</SRS>
+      <SRS>EPSG:22524</SRS>
+      <SRS>EPSG:22525</SRS>
+      <SRS>EPSG:22700</SRS>
+      <SRS>EPSG:22770</SRS>
+      <SRS>EPSG:22780</SRS>
+      <SRS>EPSG:22832</SRS>
+      <SRS>EPSG:22991</SRS>
+      <SRS>EPSG:22992</SRS>
+      <SRS>EPSG:22993</SRS>
+      <SRS>EPSG:22994</SRS>
+      <SRS>EPSG:23028</SRS>
+      <SRS>EPSG:23029</SRS>
+      <SRS>EPSG:23030</SRS>
+      <SRS>EPSG:23031</SRS>
+      <SRS>EPSG:23032</SRS>
+      <SRS>EPSG:23033</SRS>
+      <SRS>EPSG:23034</SRS>
+      <SRS>EPSG:23035</SRS>
+      <SRS>EPSG:23036</SRS>
+      <SRS>EPSG:23037</SRS>
+      <SRS>EPSG:23038</SRS>
+      <SRS>EPSG:23090</SRS>
+      <SRS>EPSG:23095</SRS>
+      <SRS>EPSG:23239</SRS>
+      <SRS>EPSG:23240</SRS>
+      <SRS>EPSG:23433</SRS>
+      <SRS>EPSG:23700</SRS>
+      <SRS>EPSG:23846</SRS>
+      <SRS>EPSG:23847</SRS>
+      <SRS>EPSG:23848</SRS>
+      <SRS>EPSG:23849</SRS>
+      <SRS>EPSG:23850</SRS>
+      <SRS>EPSG:23851</SRS>
+      <SRS>EPSG:23852</SRS>
+      <SRS>EPSG:23853</SRS>
+      <SRS>EPSG:23866</SRS>
+      <SRS>EPSG:23867</SRS>
+      <SRS>EPSG:23868</SRS>
+      <SRS>EPSG:23869</SRS>
+      <SRS>EPSG:23870</SRS>
+      <SRS>EPSG:23871</SRS>
+      <SRS>EPSG:23872</SRS>
+      <SRS>EPSG:23877</SRS>
+      <SRS>EPSG:23878</SRS>
+      <SRS>EPSG:23879</SRS>
+      <SRS>EPSG:23880</SRS>
+      <SRS>EPSG:23881</SRS>
+      <SRS>EPSG:23882</SRS>
+      <SRS>EPSG:23883</SRS>
+      <SRS>EPSG:23884</SRS>
+      <SRS>EPSG:23886</SRS>
+      <SRS>EPSG:23887</SRS>
+      <SRS>EPSG:23888</SRS>
+      <SRS>EPSG:23889</SRS>
+      <SRS>EPSG:23890</SRS>
+      <SRS>EPSG:23891</SRS>
+      <SRS>EPSG:23892</SRS>
+      <SRS>EPSG:23893</SRS>
+      <SRS>EPSG:23894</SRS>
+      <SRS>EPSG:23946</SRS>
+      <SRS>EPSG:23947</SRS>
+      <SRS>EPSG:23948</SRS>
+      <SRS>EPSG:24047</SRS>
+      <SRS>EPSG:24048</SRS>
+      <SRS>EPSG:24100</SRS>
+      <SRS>EPSG:24200</SRS>
+      <SRS>EPSG:24305</SRS>
+      <SRS>EPSG:24306</SRS>
+      <SRS>EPSG:24311</SRS>
+      <SRS>EPSG:24312</SRS>
+      <SRS>EPSG:24313</SRS>
+      <SRS>EPSG:24342</SRS>
+      <SRS>EPSG:24343</SRS>
+      <SRS>EPSG:24344</SRS>
+      <SRS>EPSG:24345</SRS>
+      <SRS>EPSG:24346</SRS>
+      <SRS>EPSG:24347</SRS>
+      <SRS>EPSG:24370</SRS>
+      <SRS>EPSG:24371</SRS>
+      <SRS>EPSG:24372</SRS>
+      <SRS>EPSG:24373</SRS>
+      <SRS>EPSG:24374</SRS>
+      <SRS>EPSG:24375</SRS>
+      <SRS>EPSG:24376</SRS>
+      <SRS>EPSG:24377</SRS>
+      <SRS>EPSG:24378</SRS>
+      <SRS>EPSG:24379</SRS>
+      <SRS>EPSG:24380</SRS>
+      <SRS>EPSG:24381</SRS>
+      <SRS>EPSG:24382</SRS>
+      <SRS>EPSG:24383</SRS>
+      <SRS>EPSG:24500</SRS>
+      <SRS>EPSG:24547</SRS>
+      <SRS>EPSG:24548</SRS>
+      <SRS>EPSG:24571</SRS>
+      <SRS>EPSG:24600</SRS>
+      <SRS>EPSG:24718</SRS>
+      <SRS>EPSG:24719</SRS>
+      <SRS>EPSG:24720</SRS>
+      <SRS>EPSG:24817</SRS>
+      <SRS>EPSG:24818</SRS>
+      <SRS>EPSG:24819</SRS>
+      <SRS>EPSG:24820</SRS>
+      <SRS>EPSG:24821</SRS>
+      <SRS>EPSG:24877</SRS>
+      <SRS>EPSG:24878</SRS>
+      <SRS>EPSG:24879</SRS>
+      <SRS>EPSG:24880</SRS>
+      <SRS>EPSG:24881</SRS>
+      <SRS>EPSG:24882</SRS>
+      <SRS>EPSG:24891</SRS>
+      <SRS>EPSG:24892</SRS>
+      <SRS>EPSG:24893</SRS>
+      <SRS>EPSG:25000</SRS>
+      <SRS>EPSG:25231</SRS>
+      <SRS>EPSG:25391</SRS>
+      <SRS>EPSG:25392</SRS>
+      <SRS>EPSG:25393</SRS>
+      <SRS>EPSG:25394</SRS>
+      <SRS>EPSG:25395</SRS>
+      <SRS>EPSG:25700</SRS>
+      <SRS>EPSG:25828</SRS>
+      <SRS>EPSG:25829</SRS>
+      <SRS>EPSG:25830</SRS>
+      <SRS>EPSG:25831</SRS>
+      <SRS>EPSG:25832</SRS>
+      <SRS>EPSG:25833</SRS>
+      <SRS>EPSG:25834</SRS>
+      <SRS>EPSG:25835</SRS>
+      <SRS>EPSG:25836</SRS>
+      <SRS>EPSG:25837</SRS>
+      <SRS>EPSG:25838</SRS>
+      <SRS>EPSG:25884</SRS>
+      <SRS>EPSG:25932</SRS>
+      <SRS>EPSG:26191</SRS>
+      <SRS>EPSG:26192</SRS>
+      <SRS>EPSG:26193</SRS>
+      <SRS>EPSG:26194</SRS>
+      <SRS>EPSG:26195</SRS>
+      <SRS>EPSG:26237</SRS>
+      <SRS>EPSG:26331</SRS>
+      <SRS>EPSG:26332</SRS>
+      <SRS>EPSG:26391</SRS>
+      <SRS>EPSG:26392</SRS>
+      <SRS>EPSG:26393</SRS>
+      <SRS>EPSG:26432</SRS>
+      <SRS>EPSG:26591</SRS>
+      <SRS>EPSG:26592</SRS>
+      <SRS>EPSG:26632</SRS>
+      <SRS>EPSG:26692</SRS>
+      <SRS>EPSG:26701</SRS>
+      <SRS>EPSG:26702</SRS>
+      <SRS>EPSG:26703</SRS>
+      <SRS>EPSG:26704</SRS>
+      <SRS>EPSG:26705</SRS>
+      <SRS>EPSG:26706</SRS>
+      <SRS>EPSG:26707</SRS>
+      <SRS>EPSG:26708</SRS>
+      <SRS>EPSG:26709</SRS>
+      <SRS>EPSG:26710</SRS>
+      <SRS>EPSG:26711</SRS>
+      <SRS>EPSG:26712</SRS>
+      <SRS>EPSG:26713</SRS>
+      <SRS>EPSG:26714</SRS>
+      <SRS>EPSG:26715</SRS>
+      <SRS>EPSG:26716</SRS>
+      <SRS>EPSG:26717</SRS>
+      <SRS>EPSG:26718</SRS>
+      <SRS>EPSG:26719</SRS>
+      <SRS>EPSG:26720</SRS>
+      <SRS>EPSG:26721</SRS>
+      <SRS>EPSG:26722</SRS>
+      <SRS>EPSG:26729</SRS>
+      <SRS>EPSG:26730</SRS>
+      <SRS>EPSG:26731</SRS>
+      <SRS>EPSG:26732</SRS>
+      <SRS>EPSG:26733</SRS>
+      <SRS>EPSG:26734</SRS>
+      <SRS>EPSG:26735</SRS>
+      <SRS>EPSG:26736</SRS>
+      <SRS>EPSG:26737</SRS>
+      <SRS>EPSG:26738</SRS>
+      <SRS>EPSG:26739</SRS>
+      <SRS>EPSG:26740</SRS>
+      <SRS>EPSG:26741</SRS>
+      <SRS>EPSG:26742</SRS>
+      <SRS>EPSG:26743</SRS>
+      <SRS>EPSG:26744</SRS>
+      <SRS>EPSG:26745</SRS>
+      <SRS>EPSG:26746</SRS>
+      <SRS>EPSG:26747</SRS>
+      <SRS>EPSG:26748</SRS>
+      <SRS>EPSG:26749</SRS>
+      <SRS>EPSG:26750</SRS>
+      <SRS>EPSG:26751</SRS>
+      <SRS>EPSG:26752</SRS>
+      <SRS>EPSG:26753</SRS>
+      <SRS>EPSG:26754</SRS>
+      <SRS>EPSG:26755</SRS>
+      <SRS>EPSG:26756</SRS>
+      <SRS>EPSG:26757</SRS>
+      <SRS>EPSG:26758</SRS>
+      <SRS>EPSG:26759</SRS>
+      <SRS>EPSG:26760</SRS>
+      <SRS>EPSG:26766</SRS>
+      <SRS>EPSG:26767</SRS>
+      <SRS>EPSG:26768</SRS>
+      <SRS>EPSG:26769</SRS>
+      <SRS>EPSG:26770</SRS>
+      <SRS>EPSG:26771</SRS>
+      <SRS>EPSG:26772</SRS>
+      <SRS>EPSG:26773</SRS>
+      <SRS>EPSG:26774</SRS>
+      <SRS>EPSG:26775</SRS>
+      <SRS>EPSG:26776</SRS>
+      <SRS>EPSG:26777</SRS>
+      <SRS>EPSG:26778</SRS>
+      <SRS>EPSG:26779</SRS>
+      <SRS>EPSG:26780</SRS>
+      <SRS>EPSG:26781</SRS>
+      <SRS>EPSG:26782</SRS>
+      <SRS>EPSG:26783</SRS>
+      <SRS>EPSG:26784</SRS>
+      <SRS>EPSG:26785</SRS>
+      <SRS>EPSG:26786</SRS>
+      <SRS>EPSG:26787</SRS>
+      <SRS>EPSG:26791</SRS>
+      <SRS>EPSG:26792</SRS>
+      <SRS>EPSG:26793</SRS>
+      <SRS>EPSG:26794</SRS>
+      <SRS>EPSG:26795</SRS>
+      <SRS>EPSG:26796</SRS>
+      <SRS>EPSG:26797</SRS>
+      <SRS>EPSG:26798</SRS>
+      <SRS>EPSG:26799</SRS>
+      <SRS>EPSG:26801</SRS>
+      <SRS>EPSG:26802</SRS>
+      <SRS>EPSG:26803</SRS>
+      <SRS>EPSG:26811</SRS>
+      <SRS>EPSG:26812</SRS>
+      <SRS>EPSG:26813</SRS>
+      <SRS>EPSG:26901</SRS>
+      <SRS>EPSG:26902</SRS>
+      <SRS>EPSG:26903</SRS>
+      <SRS>EPSG:26904</SRS>
+      <SRS>EPSG:26905</SRS>
+      <SRS>EPSG:26906</SRS>
+      <SRS>EPSG:26907</SRS>
+      <SRS>EPSG:26908</SRS>
+      <SRS>EPSG:26909</SRS>
+      <SRS>EPSG:26910</SRS>
+      <SRS>EPSG:26911</SRS>
+      <SRS>EPSG:26912</SRS>
+      <SRS>EPSG:26913</SRS>
+      <SRS>EPSG:26914</SRS>
+      <SRS>EPSG:26915</SRS>
+      <SRS>EPSG:26916</SRS>
+      <SRS>EPSG:26917</SRS>
+      <SRS>EPSG:26918</SRS>
+      <SRS>EPSG:26919</SRS>
+      <SRS>EPSG:26920</SRS>
+      <SRS>EPSG:26921</SRS>
+      <SRS>EPSG:26922</SRS>
+      <SRS>EPSG:26923</SRS>
+      <SRS>EPSG:26929</SRS>
+      <SRS>EPSG:26930</SRS>
+      <SRS>EPSG:26931</SRS>
+      <SRS>EPSG:26932</SRS>
+      <SRS>EPSG:26933</SRS>
+      <SRS>EPSG:26934</SRS>
+      <SRS>EPSG:26935</SRS>
+      <SRS>EPSG:26936</SRS>
+      <SRS>EPSG:26937</SRS>
+      <SRS>EPSG:26938</SRS>
+      <SRS>EPSG:26939</SRS>
+      <SRS>EPSG:26940</SRS>
+      <SRS>EPSG:26941</SRS>
+      <SRS>EPSG:26942</SRS>
+      <SRS>EPSG:26943</SRS>
+      <SRS>EPSG:26944</SRS>
+      <SRS>EPSG:26945</SRS>
+      <SRS>EPSG:26946</SRS>
+      <SRS>EPSG:26948</SRS>
+      <SRS>EPSG:26949</SRS>
+      <SRS>EPSG:26950</SRS>
+      <SRS>EPSG:26951</SRS>
+      <SRS>EPSG:26952</SRS>
+      <SRS>EPSG:26953</SRS>
+      <SRS>EPSG:26954</SRS>
+      <SRS>EPSG:26955</SRS>
+      <SRS>EPSG:26956</SRS>
+      <SRS>EPSG:26957</SRS>
+      <SRS>EPSG:26958</SRS>
+      <SRS>EPSG:26959</SRS>
+      <SRS>EPSG:26960</SRS>
+      <SRS>EPSG:26961</SRS>
+      <SRS>EPSG:26962</SRS>
+      <SRS>EPSG:26963</SRS>
+      <SRS>EPSG:26964</SRS>
+      <SRS>EPSG:26965</SRS>
+      <SRS>EPSG:26966</SRS>
+      <SRS>EPSG:26967</SRS>
+      <SRS>EPSG:26968</SRS>
+      <SRS>EPSG:26969</SRS>
+      <SRS>EPSG:26970</SRS>
+      <SRS>EPSG:26971</SRS>
+      <SRS>EPSG:26972</SRS>
+      <SRS>EPSG:26973</SRS>
+      <SRS>EPSG:26974</SRS>
+      <SRS>EPSG:26975</SRS>
+      <SRS>EPSG:26976</SRS>
+      <SRS>EPSG:26977</SRS>
+      <SRS>EPSG:26978</SRS>
+      <SRS>EPSG:26979</SRS>
+      <SRS>EPSG:26980</SRS>
+      <SRS>EPSG:26981</SRS>
+      <SRS>EPSG:26982</SRS>
+      <SRS>EPSG:26983</SRS>
+      <SRS>EPSG:26984</SRS>
+      <SRS>EPSG:26985</SRS>
+      <SRS>EPSG:26986</SRS>
+      <SRS>EPSG:26987</SRS>
+      <SRS>EPSG:26988</SRS>
+      <SRS>EPSG:26989</SRS>
+      <SRS>EPSG:26990</SRS>
+      <SRS>EPSG:26991</SRS>
+      <SRS>EPSG:26992</SRS>
+      <SRS>EPSG:26993</SRS>
+      <SRS>EPSG:26994</SRS>
+      <SRS>EPSG:26995</SRS>
+      <SRS>EPSG:26996</SRS>
+      <SRS>EPSG:26997</SRS>
+      <SRS>EPSG:26998</SRS>
+      <SRS>EPSG:27037</SRS>
+      <SRS>EPSG:27038</SRS>
+      <SRS>EPSG:27039</SRS>
+      <SRS>EPSG:27040</SRS>
+      <SRS>EPSG:27120</SRS>
+      <SRS>EPSG:27200</SRS>
+      <SRS>EPSG:27205</SRS>
+      <SRS>EPSG:27206</SRS>
+      <SRS>EPSG:27207</SRS>
+      <SRS>EPSG:27208</SRS>
+      <SRS>EPSG:27209</SRS>
+      <SRS>EPSG:27210</SRS>
+      <SRS>EPSG:27211</SRS>
+      <SRS>EPSG:27212</SRS>
+      <SRS>EPSG:27213</SRS>
+      <SRS>EPSG:27214</SRS>
+      <SRS>EPSG:27215</SRS>
+      <SRS>EPSG:27216</SRS>
+      <SRS>EPSG:27217</SRS>
+      <SRS>EPSG:27218</SRS>
+      <SRS>EPSG:27219</SRS>
+      <SRS>EPSG:27220</SRS>
+      <SRS>EPSG:27221</SRS>
+      <SRS>EPSG:27222</SRS>
+      <SRS>EPSG:27223</SRS>
+      <SRS>EPSG:27224</SRS>
+      <SRS>EPSG:27225</SRS>
+      <SRS>EPSG:27226</SRS>
+      <SRS>EPSG:27227</SRS>
+      <SRS>EPSG:27228</SRS>
+      <SRS>EPSG:27229</SRS>
+      <SRS>EPSG:27230</SRS>
+      <SRS>EPSG:27231</SRS>
+      <SRS>EPSG:27232</SRS>
+      <SRS>EPSG:27258</SRS>
+      <SRS>EPSG:27259</SRS>
+      <SRS>EPSG:27260</SRS>
+      <SRS>EPSG:27291</SRS>
+      <SRS>EPSG:27292</SRS>
+      <SRS>EPSG:27391</SRS>
+      <SRS>EPSG:27392</SRS>
+      <SRS>EPSG:27393</SRS>
+      <SRS>EPSG:27394</SRS>
+      <SRS>EPSG:27395</SRS>
+      <SRS>EPSG:27396</SRS>
+      <SRS>EPSG:27397</SRS>
+      <SRS>EPSG:27398</SRS>
+      <SRS>EPSG:27429</SRS>
+      <SRS>EPSG:27492</SRS>
+      <SRS>EPSG:27500</SRS>
+      <SRS>EPSG:27561</SRS>
+      <SRS>EPSG:27562</SRS>
+      <SRS>EPSG:27563</SRS>
+      <SRS>EPSG:27564</SRS>
+      <SRS>EPSG:27571</SRS>
+      <SRS>EPSG:27572</SRS>
+      <SRS>EPSG:27573</SRS>
+      <SRS>EPSG:27574</SRS>
+      <SRS>EPSG:27581</SRS>
+      <SRS>EPSG:27582</SRS>
+      <SRS>EPSG:27583</SRS>
+      <SRS>EPSG:27584</SRS>
+      <SRS>EPSG:27591</SRS>
+      <SRS>EPSG:27592</SRS>
+      <SRS>EPSG:27593</SRS>
+      <SRS>EPSG:27594</SRS>
+      <SRS>EPSG:27700</SRS>
+      <SRS>EPSG:28191</SRS>
+      <SRS>EPSG:28192</SRS>
+      <SRS>EPSG:28193</SRS>
+      <SRS>EPSG:28232</SRS>
+      <SRS>EPSG:28348</SRS>
+      <SRS>EPSG:28349</SRS>
+      <SRS>EPSG:28350</SRS>
+      <SRS>EPSG:28351</SRS>
+      <SRS>EPSG:28352</SRS>
+      <SRS>EPSG:28353</SRS>
+      <SRS>EPSG:28354</SRS>
+      <SRS>EPSG:28355</SRS>
+      <SRS>EPSG:28356</SRS>
+      <SRS>EPSG:28357</SRS>
+      <SRS>EPSG:28358</SRS>
+      <SRS>EPSG:28402</SRS>
+      <SRS>EPSG:28403</SRS>
+      <SRS>EPSG:28404</SRS>
+      <SRS>EPSG:28405</SRS>
+      <SRS>EPSG:28406</SRS>
+      <SRS>EPSG:28407</SRS>
+      <SRS>EPSG:28408</SRS>
+      <SRS>EPSG:28409</SRS>
+      <SRS>EPSG:28410</SRS>
+      <SRS>EPSG:28411</SRS>
+      <SRS>EPSG:28412</SRS>
+      <SRS>EPSG:28413</SRS>
+      <SRS>EPSG:28414</SRS>
+      <SRS>EPSG:28415</SRS>
+      <SRS>EPSG:28416</SRS>
+      <SRS>EPSG:28417</SRS>
+      <SRS>EPSG:28418</SRS>
+      <SRS>EPSG:28419</SRS>
+      <SRS>EPSG:28420</SRS>
+      <SRS>EPSG:28421</SRS>
+      <SRS>EPSG:28422</SRS>
+      <SRS>EPSG:28423</SRS>
+      <SRS>EPSG:28424</SRS>
+      <SRS>EPSG:28425</SRS>
+      <SRS>EPSG:28426</SRS>
+      <SRS>EPSG:28427</SRS>
+      <SRS>EPSG:28428</SRS>
+      <SRS>EPSG:28429</SRS>
+      <SRS>EPSG:28430</SRS>
+      <SRS>EPSG:28431</SRS>
+      <SRS>EPSG:28432</SRS>
+      <SRS>EPSG:28462</SRS>
+      <SRS>EPSG:28463</SRS>
+      <SRS>EPSG:28464</SRS>
+      <SRS>EPSG:28465</SRS>
+      <SRS>EPSG:28466</SRS>
+      <SRS>EPSG:28467</SRS>
+      <SRS>EPSG:28468</SRS>
+      <SRS>EPSG:28469</SRS>
+      <SRS>EPSG:28470</SRS>
+      <SRS>EPSG:28471</SRS>
+      <SRS>EPSG:28472</SRS>
+      <SRS>EPSG:28473</SRS>
+      <SRS>EPSG:28474</SRS>
+      <SRS>EPSG:28475</SRS>
+      <SRS>EPSG:28476</SRS>
+      <SRS>EPSG:28477</SRS>
+      <SRS>EPSG:28478</SRS>
+      <SRS>EPSG:28479</SRS>
+      <SRS>EPSG:28480</SRS>
+      <SRS>EPSG:28481</SRS>
+      <SRS>EPSG:28482</SRS>
+      <SRS>EPSG:28483</SRS>
+      <SRS>EPSG:28484</SRS>
+      <SRS>EPSG:28485</SRS>
+      <SRS>EPSG:28486</SRS>
+      <SRS>EPSG:28487</SRS>
+      <SRS>EPSG:28488</SRS>
+      <SRS>EPSG:28489</SRS>
+      <SRS>EPSG:28490</SRS>
+      <SRS>EPSG:28491</SRS>
+      <SRS>EPSG:28492</SRS>
+      <SRS>EPSG:28600</SRS>
+      <SRS>EPSG:28991</SRS>
+      <SRS>EPSG:28992</SRS>
+      <SRS>EPSG:29100</SRS>
+      <SRS>EPSG:29101</SRS>
+      <SRS>EPSG:29118</SRS>
+      <SRS>EPSG:29119</SRS>
+      <SRS>EPSG:29120</SRS>
+      <SRS>EPSG:29121</SRS>
+      <SRS>EPSG:29122</SRS>
+      <SRS>EPSG:29168</SRS>
+      <SRS>EPSG:29169</SRS>
+      <SRS>EPSG:29170</SRS>
+      <SRS>EPSG:29171</SRS>
+      <SRS>EPSG:29172</SRS>
+      <SRS>EPSG:29177</SRS>
+      <SRS>EPSG:29178</SRS>
+      <SRS>EPSG:29179</SRS>
+      <SRS>EPSG:29180</SRS>
+      <SRS>EPSG:29181</SRS>
+      <SRS>EPSG:29182</SRS>
+      <SRS>EPSG:29183</SRS>
+      <SRS>EPSG:29184</SRS>
+      <SRS>EPSG:29185</SRS>
+      <SRS>EPSG:29187</SRS>
+      <SRS>EPSG:29188</SRS>
+      <SRS>EPSG:29189</SRS>
+      <SRS>EPSG:29190</SRS>
+      <SRS>EPSG:29191</SRS>
+      <SRS>EPSG:29192</SRS>
+      <SRS>EPSG:29193</SRS>
+      <SRS>EPSG:29194</SRS>
+      <SRS>EPSG:29195</SRS>
+      <SRS>EPSG:29220</SRS>
+      <SRS>EPSG:29221</SRS>
+      <SRS>EPSG:29333</SRS>
+      <SRS>EPSG:29371</SRS>
+      <SRS>EPSG:29373</SRS>
+      <SRS>EPSG:29375</SRS>
+      <SRS>EPSG:29377</SRS>
+      <SRS>EPSG:29379</SRS>
+      <SRS>EPSG:29381</SRS>
+      <SRS>EPSG:29383</SRS>
+      <SRS>EPSG:29385</SRS>
+      <SRS>EPSG:29635</SRS>
+      <SRS>EPSG:29636</SRS>
+      <SRS>EPSG:29700</SRS>
+      <SRS>EPSG:29701</SRS>
+      <SRS>EPSG:29702</SRS>
+      <SRS>EPSG:29738</SRS>
+      <SRS>EPSG:29739</SRS>
+      <SRS>EPSG:29849</SRS>
+      <SRS>EPSG:29850</SRS>
+      <SRS>EPSG:29871</SRS>
+      <SRS>EPSG:29872</SRS>
+      <SRS>EPSG:29873</SRS>
+      <SRS>EPSG:29900</SRS>
+      <SRS>EPSG:29901</SRS>
+      <SRS>EPSG:29902</SRS>
+      <SRS>EPSG:29903</SRS>
+      <SRS>EPSG:30161</SRS>
+      <SRS>EPSG:30162</SRS>
+      <SRS>EPSG:30163</SRS>
+      <SRS>EPSG:30164</SRS>
+      <SRS>EPSG:30165</SRS>
+      <SRS>EPSG:30166</SRS>
+      <SRS>EPSG:30167</SRS>
+      <SRS>EPSG:30168</SRS>
+      <SRS>EPSG:30169</SRS>
+      <SRS>EPSG:30170</SRS>
+      <SRS>EPSG:30171</SRS>
+      <SRS>EPSG:30172</SRS>
+      <SRS>EPSG:30173</SRS>
+      <SRS>EPSG:30174</SRS>
+      <SRS>EPSG:30175</SRS>
+      <SRS>EPSG:30176</SRS>
+      <SRS>EPSG:30177</SRS>
+      <SRS>EPSG:30178</SRS>
+      <SRS>EPSG:30179</SRS>
+      <SRS>EPSG:30200</SRS>
+      <SRS>EPSG:30339</SRS>
+      <SRS>EPSG:30340</SRS>
+      <SRS>EPSG:30491</SRS>
+      <SRS>EPSG:30492</SRS>
+      <SRS>EPSG:30493</SRS>
+      <SRS>EPSG:30494</SRS>
+      <SRS>EPSG:30729</SRS>
+      <SRS>EPSG:30730</SRS>
+      <SRS>EPSG:30731</SRS>
+      <SRS>EPSG:30732</SRS>
+      <SRS>EPSG:30791</SRS>
+      <SRS>EPSG:30792</SRS>
+      <SRS>EPSG:30800</SRS>
+      <SRS>EPSG:31028</SRS>
+      <SRS>EPSG:31121</SRS>
+      <SRS>EPSG:31154</SRS>
+      <SRS>EPSG:31170</SRS>
+      <SRS>EPSG:31171</SRS>
+      <SRS>EPSG:31251</SRS>
+      <SRS>EPSG:31252</SRS>
+      <SRS>EPSG:31253</SRS>
+      <SRS>EPSG:31254</SRS>
+      <SRS>EPSG:31255</SRS>
+      <SRS>EPSG:31256</SRS>
+      <SRS>EPSG:31257</SRS>
+      <SRS>EPSG:31258</SRS>
+      <SRS>EPSG:31259</SRS>
+      <SRS>EPSG:31265</SRS>
+      <SRS>EPSG:31266</SRS>
+      <SRS>EPSG:31267</SRS>
+      <SRS>EPSG:31268</SRS>
+      <SRS>EPSG:31275</SRS>
+      <SRS>EPSG:31276</SRS>
+      <SRS>EPSG:31277</SRS>
+      <SRS>EPSG:31278</SRS>
+      <SRS>EPSG:31279</SRS>
+      <SRS>EPSG:31281</SRS>
+      <SRS>EPSG:31282</SRS>
+      <SRS>EPSG:31283</SRS>
+      <SRS>EPSG:31284</SRS>
+      <SRS>EPSG:31285</SRS>
+      <SRS>EPSG:31286</SRS>
+      <SRS>EPSG:31287</SRS>
+      <SRS>EPSG:31288</SRS>
+      <SRS>EPSG:31289</SRS>
+      <SRS>EPSG:31290</SRS>
+      <SRS>EPSG:31291</SRS>
+      <SRS>EPSG:31292</SRS>
+      <SRS>EPSG:31293</SRS>
+      <SRS>EPSG:31294</SRS>
+      <SRS>EPSG:31295</SRS>
+      <SRS>EPSG:31296</SRS>
+      <SRS>EPSG:31297</SRS>
+      <SRS>EPSG:31300</SRS>
+      <SRS>EPSG:31370</SRS>
+      <SRS>EPSG:31461</SRS>
+      <SRS>EPSG:31462</SRS>
+      <SRS>EPSG:31463</SRS>
+      <SRS>EPSG:31464</SRS>
+      <SRS>EPSG:31465</SRS>
+      <SRS>EPSG:31466</SRS>
+      <SRS>EPSG:31467</SRS>
+      <SRS>EPSG:31468</SRS>
+      <SRS>EPSG:31469</SRS>
+      <SRS>EPSG:31528</SRS>
+      <SRS>EPSG:31529</SRS>
+      <SRS>EPSG:31600</SRS>
+      <SRS>EPSG:31700</SRS>
+      <SRS>EPSG:31838</SRS>
+      <SRS>EPSG:31839</SRS>
+      <SRS>EPSG:31900</SRS>
+      <SRS>EPSG:31901</SRS>
+      <SRS>EPSG:31965</SRS>
+      <SRS>EPSG:31966</SRS>
+      <SRS>EPSG:31967</SRS>
+      <SRS>EPSG:31968</SRS>
+      <SRS>EPSG:31969</SRS>
+      <SRS>EPSG:31970</SRS>
+      <SRS>EPSG:31971</SRS>
+      <SRS>EPSG:31972</SRS>
+      <SRS>EPSG:31973</SRS>
+      <SRS>EPSG:31974</SRS>
+      <SRS>EPSG:31975</SRS>
+      <SRS>EPSG:31976</SRS>
+      <SRS>EPSG:31977</SRS>
+      <SRS>EPSG:31978</SRS>
+      <SRS>EPSG:31979</SRS>
+      <SRS>EPSG:31980</SRS>
+      <SRS>EPSG:31981</SRS>
+      <SRS>EPSG:31982</SRS>
+      <SRS>EPSG:31983</SRS>
+      <SRS>EPSG:31984</SRS>
+      <SRS>EPSG:31985</SRS>
+      <SRS>EPSG:31986</SRS>
+      <SRS>EPSG:31987</SRS>
+      <SRS>EPSG:31988</SRS>
+      <SRS>EPSG:31989</SRS>
+      <SRS>EPSG:31990</SRS>
+      <SRS>EPSG:31991</SRS>
+      <SRS>EPSG:31992</SRS>
+      <SRS>EPSG:31993</SRS>
+      <SRS>EPSG:31994</SRS>
+      <SRS>EPSG:31995</SRS>
+      <SRS>EPSG:31996</SRS>
+      <SRS>EPSG:31997</SRS>
+      <SRS>EPSG:31998</SRS>
+      <SRS>EPSG:31999</SRS>
+      <SRS>EPSG:32000</SRS>
+      <SRS>EPSG:32001</SRS>
+      <SRS>EPSG:32002</SRS>
+      <SRS>EPSG:32003</SRS>
+      <SRS>EPSG:32005</SRS>
+      <SRS>EPSG:32006</SRS>
+      <SRS>EPSG:32007</SRS>
+      <SRS>EPSG:32008</SRS>
+      <SRS>EPSG:32009</SRS>
+      <SRS>EPSG:32010</SRS>
+      <SRS>EPSG:32011</SRS>
+      <SRS>EPSG:32012</SRS>
+      <SRS>EPSG:32013</SRS>
+      <SRS>EPSG:32014</SRS>
+      <SRS>EPSG:32015</SRS>
+      <SRS>EPSG:32016</SRS>
+      <SRS>EPSG:32017</SRS>
+      <SRS>EPSG:32018</SRS>
+      <SRS>EPSG:32019</SRS>
+      <SRS>EPSG:32020</SRS>
+      <SRS>EPSG:32021</SRS>
+      <SRS>EPSG:32022</SRS>
+      <SRS>EPSG:32023</SRS>
+      <SRS>EPSG:32024</SRS>
+      <SRS>EPSG:32025</SRS>
+      <SRS>EPSG:32026</SRS>
+      <SRS>EPSG:32027</SRS>
+      <SRS>EPSG:32028</SRS>
+      <SRS>EPSG:32029</SRS>
+      <SRS>EPSG:32030</SRS>
+      <SRS>EPSG:32031</SRS>
+      <SRS>EPSG:32033</SRS>
+      <SRS>EPSG:32034</SRS>
+      <SRS>EPSG:32035</SRS>
+      <SRS>EPSG:32036</SRS>
+      <SRS>EPSG:32037</SRS>
+      <SRS>EPSG:32038</SRS>
+      <SRS>EPSG:32039</SRS>
+      <SRS>EPSG:32040</SRS>
+      <SRS>EPSG:32041</SRS>
+      <SRS>EPSG:32042</SRS>
+      <SRS>EPSG:32043</SRS>
+      <SRS>EPSG:32044</SRS>
+      <SRS>EPSG:32045</SRS>
+      <SRS>EPSG:32046</SRS>
+      <SRS>EPSG:32047</SRS>
+      <SRS>EPSG:32048</SRS>
+      <SRS>EPSG:32049</SRS>
+      <SRS>EPSG:32050</SRS>
+      <SRS>EPSG:32051</SRS>
+      <SRS>EPSG:32052</SRS>
+      <SRS>EPSG:32053</SRS>
+      <SRS>EPSG:32054</SRS>
+      <SRS>EPSG:32055</SRS>
+      <SRS>EPSG:32056</SRS>
+      <SRS>EPSG:32057</SRS>
+      <SRS>EPSG:32058</SRS>
+      <SRS>EPSG:32061</SRS>
+      <SRS>EPSG:32062</SRS>
+      <SRS>EPSG:32064</SRS>
+      <SRS>EPSG:32065</SRS>
+      <SRS>EPSG:32066</SRS>
+      <SRS>EPSG:32067</SRS>
+      <SRS>EPSG:32074</SRS>
+      <SRS>EPSG:32075</SRS>
+      <SRS>EPSG:32076</SRS>
+      <SRS>EPSG:32077</SRS>
+      <SRS>EPSG:32081</SRS>
+      <SRS>EPSG:32082</SRS>
+      <SRS>EPSG:32083</SRS>
+      <SRS>EPSG:32084</SRS>
+      <SRS>EPSG:32085</SRS>
+      <SRS>EPSG:32086</SRS>
+      <SRS>EPSG:32098</SRS>
+      <SRS>EPSG:32099</SRS>
+      <SRS>EPSG:32100</SRS>
+      <SRS>EPSG:32104</SRS>
+      <SRS>EPSG:32107</SRS>
+      <SRS>EPSG:32108</SRS>
+      <SRS>EPSG:32109</SRS>
+      <SRS>EPSG:32110</SRS>
+      <SRS>EPSG:32111</SRS>
+      <SRS>EPSG:32112</SRS>
+      <SRS>EPSG:32113</SRS>
+      <SRS>EPSG:32114</SRS>
+      <SRS>EPSG:32115</SRS>
+      <SRS>EPSG:32116</SRS>
+      <SRS>EPSG:32117</SRS>
+      <SRS>EPSG:32118</SRS>
+      <SRS>EPSG:32119</SRS>
+      <SRS>EPSG:32120</SRS>
+      <SRS>EPSG:32121</SRS>
+      <SRS>EPSG:32122</SRS>
+      <SRS>EPSG:32123</SRS>
+      <SRS>EPSG:32124</SRS>
+      <SRS>EPSG:32125</SRS>
+      <SRS>EPSG:32126</SRS>
+      <SRS>EPSG:32127</SRS>
+      <SRS>EPSG:32128</SRS>
+      <SRS>EPSG:32129</SRS>
+      <SRS>EPSG:32130</SRS>
+      <SRS>EPSG:32133</SRS>
+      <SRS>EPSG:32134</SRS>
+      <SRS>EPSG:32135</SRS>
+      <SRS>EPSG:32136</SRS>
+      <SRS>EPSG:32137</SRS>
+      <SRS>EPSG:32138</SRS>
+      <SRS>EPSG:32139</SRS>
+      <SRS>EPSG:32140</SRS>
+      <SRS>EPSG:32141</SRS>
+      <SRS>EPSG:32142</SRS>
+      <SRS>EPSG:32143</SRS>
+      <SRS>EPSG:32144</SRS>
+      <SRS>EPSG:32145</SRS>
+      <SRS>EPSG:32146</SRS>
+      <SRS>EPSG:32147</SRS>
+      <SRS>EPSG:32148</SRS>
+      <SRS>EPSG:32149</SRS>
+      <SRS>EPSG:32150</SRS>
+      <SRS>EPSG:32151</SRS>
+      <SRS>EPSG:32152</SRS>
+      <SRS>EPSG:32153</SRS>
+      <SRS>EPSG:32154</SRS>
+      <SRS>EPSG:32155</SRS>
+      <SRS>EPSG:32156</SRS>
+      <SRS>EPSG:32157</SRS>
+      <SRS>EPSG:32158</SRS>
+      <SRS>EPSG:32161</SRS>
+      <SRS>EPSG:32164</SRS>
+      <SRS>EPSG:32165</SRS>
+      <SRS>EPSG:32166</SRS>
+      <SRS>EPSG:32167</SRS>
+      <SRS>EPSG:32180</SRS>
+      <SRS>EPSG:32181</SRS>
+      <SRS>EPSG:32182</SRS>
+      <SRS>EPSG:32183</SRS>
+      <SRS>EPSG:32184</SRS>
+      <SRS>EPSG:32185</SRS>
+      <SRS>EPSG:32186</SRS>
+      <SRS>EPSG:32187</SRS>
+      <SRS>EPSG:32188</SRS>
+      <SRS>EPSG:32189</SRS>
+      <SRS>EPSG:32190</SRS>
+      <SRS>EPSG:32191</SRS>
+      <SRS>EPSG:32192</SRS>
+      <SRS>EPSG:32193</SRS>
+      <SRS>EPSG:32194</SRS>
+      <SRS>EPSG:32195</SRS>
+      <SRS>EPSG:32196</SRS>
+      <SRS>EPSG:32197</SRS>
+      <SRS>EPSG:32198</SRS>
+      <SRS>EPSG:32199</SRS>
+      <SRS>EPSG:32201</SRS>
+      <SRS>EPSG:32202</SRS>
+      <SRS>EPSG:32203</SRS>
+      <SRS>EPSG:32204</SRS>
+      <SRS>EPSG:32205</SRS>
+      <SRS>EPSG:32206</SRS>
+      <SRS>EPSG:32207</SRS>
+      <SRS>EPSG:32208</SRS>
+      <SRS>EPSG:32209</SRS>
+      <SRS>EPSG:32210</SRS>
+      <SRS>EPSG:32211</SRS>
+      <SRS>EPSG:32212</SRS>
+      <SRS>EPSG:32213</SRS>
+      <SRS>EPSG:32214</SRS>
+      <SRS>EPSG:32215</SRS>
+      <SRS>EPSG:32216</SRS>
+      <SRS>EPSG:32217</SRS>
+      <SRS>EPSG:32218</SRS>
+      <SRS>EPSG:32219</SRS>
+      <SRS>EPSG:32220</SRS>
+      <SRS>EPSG:32221</SRS>
+      <SRS>EPSG:32222</SRS>
+      <SRS>EPSG:32223</SRS>
+      <SRS>EPSG:32224</SRS>
+      <SRS>EPSG:32225</SRS>
+      <SRS>EPSG:32226</SRS>
+      <SRS>EPSG:32227</SRS>
+      <SRS>EPSG:32228</SRS>
+      <SRS>EPSG:32229</SRS>
+      <SRS>EPSG:32230</SRS>
+      <SRS>EPSG:32231</SRS>
+      <SRS>EPSG:32232</SRS>
+      <SRS>EPSG:32233</SRS>
+      <SRS>EPSG:32234</SRS>
+      <SRS>EPSG:32235</SRS>
+      <SRS>EPSG:32236</SRS>
+      <SRS>EPSG:32237</SRS>
+      <SRS>EPSG:32238</SRS>
+      <SRS>EPSG:32239</SRS>
+      <SRS>EPSG:32240</SRS>
+      <SRS>EPSG:32241</SRS>
+      <SRS>EPSG:32242</SRS>
+      <SRS>EPSG:32243</SRS>
+      <SRS>EPSG:32244</SRS>
+      <SRS>EPSG:32245</SRS>
+      <SRS>EPSG:32246</SRS>
+      <SRS>EPSG:32247</SRS>
+      <SRS>EPSG:32248</SRS>
+      <SRS>EPSG:32249</SRS>
+      <SRS>EPSG:32250</SRS>
+      <SRS>EPSG:32251</SRS>
+      <SRS>EPSG:32252</SRS>
+      <SRS>EPSG:32253</SRS>
+      <SRS>EPSG:32254</SRS>
+      <SRS>EPSG:32255</SRS>
+      <SRS>EPSG:32256</SRS>
+      <SRS>EPSG:32257</SRS>
+      <SRS>EPSG:32258</SRS>
+      <SRS>EPSG:32259</SRS>
+      <SRS>EPSG:32260</SRS>
+      <SRS>EPSG:32301</SRS>
+      <SRS>EPSG:32302</SRS>
+      <SRS>EPSG:32303</SRS>
+      <SRS>EPSG:32304</SRS>
+      <SRS>EPSG:32305</SRS>
+      <SRS>EPSG:32306</SRS>
+      <SRS>EPSG:32307</SRS>
+      <SRS>EPSG:32308</SRS>
+      <SRS>EPSG:32309</SRS>
+      <SRS>EPSG:32310</SRS>
+      <SRS>EPSG:32311</SRS>
+      <SRS>EPSG:32312</SRS>
+      <SRS>EPSG:32313</SRS>
+      <SRS>EPSG:32314</SRS>
+      <SRS>EPSG:32315</SRS>
+      <SRS>EPSG:32316</SRS>
+      <SRS>EPSG:32317</SRS>
+      <SRS>EPSG:32318</SRS>
+      <SRS>EPSG:32319</SRS>
+      <SRS>EPSG:32320</SRS>
+      <SRS>EPSG:32321</SRS>
+      <SRS>EPSG:32322</SRS>
+      <SRS>EPSG:32323</SRS>
+      <SRS>EPSG:32324</SRS>
+      <SRS>EPSG:32325</SRS>
+      <SRS>EPSG:32326</SRS>
+      <SRS>EPSG:32327</SRS>
+      <SRS>EPSG:32328</SRS>
+      <SRS>EPSG:32329</SRS>
+      <SRS>EPSG:32330</SRS>
+      <SRS>EPSG:32331</SRS>
+      <SRS>EPSG:32332</SRS>
+      <SRS>EPSG:32333</SRS>
+      <SRS>EPSG:32334</SRS>
+      <SRS>EPSG:32335</SRS>
+      <SRS>EPSG:32336</SRS>
+      <SRS>EPSG:32337</SRS>
+      <SRS>EPSG:32338</SRS>
+      <SRS>EPSG:32339</SRS>
+      <SRS>EPSG:32340</SRS>
+      <SRS>EPSG:32341</SRS>
+      <SRS>EPSG:32342</SRS>
+      <SRS>EPSG:32343</SRS>
+      <SRS>EPSG:32344</SRS>
+      <SRS>EPSG:32345</SRS>
+      <SRS>EPSG:32346</SRS>
+      <SRS>EPSG:32347</SRS>
+      <SRS>EPSG:32348</SRS>
+      <SRS>EPSG:32349</SRS>
+      <SRS>EPSG:32350</SRS>
+      <SRS>EPSG:32351</SRS>
+      <SRS>EPSG:32352</SRS>
+      <SRS>EPSG:32353</SRS>
+      <SRS>EPSG:32354</SRS>
+      <SRS>EPSG:32355</SRS>
+      <SRS>EPSG:32356</SRS>
+      <SRS>EPSG:32357</SRS>
+      <SRS>EPSG:32358</SRS>
+      <SRS>EPSG:32359</SRS>
+      <SRS>EPSG:32360</SRS>
+      <SRS>EPSG:32401</SRS>
+      <SRS>EPSG:32402</SRS>
+      <SRS>EPSG:32403</SRS>
+      <SRS>EPSG:32404</SRS>
+      <SRS>EPSG:32405</SRS>
+      <SRS>EPSG:32406</SRS>
+      <SRS>EPSG:32407</SRS>
+      <SRS>EPSG:32408</SRS>
+      <SRS>EPSG:32409</SRS>
+      <SRS>EPSG:32410</SRS>
+      <SRS>EPSG:32411</SRS>
+      <SRS>EPSG:32412</SRS>
+      <SRS>EPSG:32413</SRS>
+      <SRS>EPSG:32414</SRS>
+      <SRS>EPSG:32415</SRS>
+      <SRS>EPSG:32416</SRS>
+      <SRS>EPSG:32417</SRS>
+      <SRS>EPSG:32418</SRS>
+      <SRS>EPSG:32419</SRS>
+      <SRS>EPSG:32420</SRS>
+      <SRS>EPSG:32421</SRS>
+      <SRS>EPSG:32422</SRS>
+      <SRS>EPSG:32423</SRS>
+      <SRS>EPSG:32424</SRS>
+      <SRS>EPSG:32425</SRS>
+      <SRS>EPSG:32426</SRS>
+      <SRS>EPSG:32427</SRS>
+      <SRS>EPSG:32428</SRS>
+      <SRS>EPSG:32429</SRS>
+      <SRS>EPSG:32430</SRS>
+      <SRS>EPSG:32431</SRS>
+      <SRS>EPSG:32432</SRS>
+      <SRS>EPSG:32433</SRS>
+      <SRS>EPSG:32434</SRS>
+      <SRS>EPSG:32435</SRS>
+      <SRS>EPSG:32436</SRS>
+      <SRS>EPSG:32437</SRS>
+      <SRS>EPSG:32438</SRS>
+      <SRS>EPSG:32439</SRS>
+      <SRS>EPSG:32440</SRS>
+      <SRS>EPSG:32441</SRS>
+      <SRS>EPSG:32442</SRS>
+      <SRS>EPSG:32443</SRS>
+      <SRS>EPSG:32444</SRS>
+      <SRS>EPSG:32445</SRS>
+      <SRS>EPSG:32446</SRS>
+      <SRS>EPSG:32447</SRS>
+      <SRS>EPSG:32448</SRS>
+      <SRS>EPSG:32449</SRS>
+      <SRS>EPSG:32450</SRS>
+      <SRS>EPSG:32451</SRS>
+      <SRS>EPSG:32452</SRS>
+      <SRS>EPSG:32453</SRS>
+      <SRS>EPSG:32454</SRS>
+      <SRS>EPSG:32455</SRS>
+      <SRS>EPSG:32456</SRS>
+      <SRS>EPSG:32457</SRS>
+      <SRS>EPSG:32458</SRS>
+      <SRS>EPSG:32459</SRS>
+      <SRS>EPSG:32460</SRS>
+      <SRS>EPSG:32501</SRS>
+      <SRS>EPSG:32502</SRS>
+      <SRS>EPSG:32503</SRS>
+      <SRS>EPSG:32504</SRS>
+      <SRS>EPSG:32505</SRS>
+      <SRS>EPSG:32506</SRS>
+      <SRS>EPSG:32507</SRS>
+      <SRS>EPSG:32508</SRS>
+      <SRS>EPSG:32509</SRS>
+      <SRS>EPSG:32510</SRS>
+      <SRS>EPSG:32511</SRS>
+      <SRS>EPSG:32512</SRS>
+      <SRS>EPSG:32513</SRS>
+      <SRS>EPSG:32514</SRS>
+      <SRS>EPSG:32515</SRS>
+      <SRS>EPSG:32516</SRS>
+      <SRS>EPSG:32517</SRS>
+      <SRS>EPSG:32518</SRS>
+      <SRS>EPSG:32519</SRS>
+      <SRS>EPSG:32520</SRS>
+      <SRS>EPSG:32521</SRS>
+      <SRS>EPSG:32522</SRS>
+      <SRS>EPSG:32523</SRS>
+      <SRS>EPSG:32524</SRS>
+      <SRS>EPSG:32525</SRS>
+      <SRS>EPSG:32526</SRS>
+      <SRS>EPSG:32527</SRS>
+      <SRS>EPSG:32528</SRS>
+      <SRS>EPSG:32529</SRS>
+      <SRS>EPSG:32530</SRS>
+      <SRS>EPSG:32531</SRS>
+      <SRS>EPSG:32532</SRS>
+      <SRS>EPSG:32533</SRS>
+      <SRS>EPSG:32534</SRS>
+      <SRS>EPSG:32535</SRS>
+      <SRS>EPSG:32536</SRS>
+      <SRS>EPSG:32537</SRS>
+      <SRS>EPSG:32538</SRS>
+      <SRS>EPSG:32539</SRS>
+      <SRS>EPSG:32540</SRS>
+      <SRS>EPSG:32541</SRS>
+      <SRS>EPSG:32542</SRS>
+      <SRS>EPSG:32543</SRS>
+      <SRS>EPSG:32544</SRS>
+      <SRS>EPSG:32545</SRS>
+      <SRS>EPSG:32546</SRS>
+      <SRS>EPSG:32547</SRS>
+      <SRS>EPSG:32548</SRS>
+      <SRS>EPSG:32549</SRS>
+      <SRS>EPSG:32550</SRS>
+      <SRS>EPSG:32551</SRS>
+      <SRS>EPSG:32552</SRS>
+      <SRS>EPSG:32553</SRS>
+      <SRS>EPSG:32554</SRS>
+      <SRS>EPSG:32555</SRS>
+      <SRS>EPSG:32556</SRS>
+      <SRS>EPSG:32557</SRS>
+      <SRS>EPSG:32558</SRS>
+      <SRS>EPSG:32559</SRS>
+      <SRS>EPSG:32560</SRS>
+      <SRS>EPSG:32600</SRS>
+      <SRS>EPSG:32601</SRS>
+      <SRS>EPSG:32602</SRS>
+      <SRS>EPSG:32603</SRS>
+      <SRS>EPSG:32604</SRS>
+      <SRS>EPSG:32605</SRS>
+      <SRS>EPSG:32606</SRS>
+      <SRS>EPSG:32607</SRS>
+      <SRS>EPSG:32608</SRS>
+      <SRS>EPSG:32609</SRS>
+      <SRS>EPSG:32610</SRS>
+      <SRS>EPSG:32611</SRS>
+      <SRS>EPSG:32612</SRS>
+      <SRS>EPSG:32613</SRS>
+      <SRS>EPSG:32614</SRS>
+      <SRS>EPSG:32615</SRS>
+      <SRS>EPSG:32616</SRS>
+      <SRS>EPSG:32617</SRS>
+      <SRS>EPSG:32618</SRS>
+      <SRS>EPSG:32619</SRS>
+      <SRS>EPSG:32620</SRS>
+      <SRS>EPSG:32621</SRS>
+      <SRS>EPSG:32622</SRS>
+      <SRS>EPSG:32623</SRS>
+      <SRS>EPSG:32624</SRS>
+      <SRS>EPSG:32625</SRS>
+      <SRS>EPSG:32626</SRS>
+      <SRS>EPSG:32627</SRS>
+      <SRS>EPSG:32628</SRS>
+      <SRS>EPSG:32629</SRS>
+      <SRS>EPSG:32630</SRS>
+      <SRS>EPSG:32631</SRS>
+      <SRS>EPSG:32632</SRS>
+      <SRS>EPSG:32633</SRS>
+      <SRS>EPSG:32634</SRS>
+      <SRS>EPSG:32635</SRS>
+      <SRS>EPSG:32636</SRS>
+      <SRS>EPSG:32637</SRS>
+      <SRS>EPSG:32638</SRS>
+      <SRS>EPSG:32639</SRS>
+      <SRS>EPSG:32640</SRS>
+      <SRS>EPSG:32641</SRS>
+      <SRS>EPSG:32642</SRS>
+      <SRS>EPSG:32643</SRS>
+      <SRS>EPSG:32644</SRS>
+      <SRS>EPSG:32645</SRS>
+      <SRS>EPSG:32646</SRS>
+      <SRS>EPSG:32647</SRS>
+      <SRS>EPSG:32648</SRS>
+      <SRS>EPSG:32649</SRS>
+      <SRS>EPSG:32650</SRS>
+      <SRS>EPSG:32651</SRS>
+      <SRS>EPSG:32652</SRS>
+      <SRS>EPSG:32653</SRS>
+      <SRS>EPSG:32654</SRS>
+      <SRS>EPSG:32655</SRS>
+      <SRS>EPSG:32656</SRS>
+      <SRS>EPSG:32657</SRS>
+      <SRS>EPSG:32658</SRS>
+      <SRS>EPSG:32659</SRS>
+      <SRS>EPSG:32660</SRS>
+      <SRS>EPSG:32661</SRS>
+      <SRS>EPSG:32662</SRS>
+      <SRS>EPSG:32664</SRS>
+      <SRS>EPSG:32665</SRS>
+      <SRS>EPSG:32666</SRS>
+      <SRS>EPSG:32667</SRS>
+      <SRS>EPSG:32700</SRS>
+      <SRS>EPSG:32701</SRS>
+      <SRS>EPSG:32702</SRS>
+      <SRS>EPSG:32703</SRS>
+      <SRS>EPSG:32704</SRS>
+      <SRS>EPSG:32705</SRS>
+      <SRS>EPSG:32706</SRS>
+      <SRS>EPSG:32707</SRS>
+      <SRS>EPSG:32708</SRS>
+      <SRS>EPSG:32709</SRS>
+      <SRS>EPSG:32710</SRS>
+      <SRS>EPSG:32711</SRS>
+      <SRS>EPSG:32712</SRS>
+      <SRS>EPSG:32713</SRS>
+      <SRS>EPSG:32714</SRS>
+      <SRS>EPSG:32715</SRS>
+      <SRS>EPSG:32716</SRS>
+      <SRS>EPSG:32717</SRS>
+      <SRS>EPSG:32718</SRS>
+      <SRS>EPSG:32719</SRS>
+      <SRS>EPSG:32720</SRS>
+      <SRS>EPSG:32721</SRS>
+      <SRS>EPSG:32722</SRS>
+      <SRS>EPSG:32723</SRS>
+      <SRS>EPSG:32724</SRS>
+      <SRS>EPSG:32725</SRS>
+      <SRS>EPSG:32726</SRS>
+      <SRS>EPSG:32727</SRS>
+      <SRS>EPSG:32728</SRS>
+      <SRS>EPSG:32729</SRS>
+      <SRS>EPSG:32730</SRS>
+      <SRS>EPSG:32731</SRS>
+      <SRS>EPSG:32732</SRS>
+      <SRS>EPSG:32733</SRS>
+      <SRS>EPSG:32734</SRS>
+      <SRS>EPSG:32735</SRS>
+      <SRS>EPSG:32736</SRS>
+      <SRS>EPSG:32737</SRS>
+      <SRS>EPSG:32738</SRS>
+      <SRS>EPSG:32739</SRS>
+      <SRS>EPSG:32740</SRS>
+      <SRS>EPSG:32741</SRS>
+      <SRS>EPSG:32742</SRS>
+      <SRS>EPSG:32743</SRS>
+      <SRS>EPSG:32744</SRS>
+      <SRS>EPSG:32745</SRS>
+      <SRS>EPSG:32746</SRS>
+      <SRS>EPSG:32747</SRS>
+      <SRS>EPSG:32748</SRS>
+      <SRS>EPSG:32749</SRS>
+      <SRS>EPSG:32750</SRS>
+      <SRS>EPSG:32751</SRS>
+      <SRS>EPSG:32752</SRS>
+      <SRS>EPSG:32753</SRS>
+      <SRS>EPSG:32754</SRS>
+      <SRS>EPSG:32755</SRS>
+      <SRS>EPSG:32756</SRS>
+      <SRS>EPSG:32757</SRS>
+      <SRS>EPSG:32758</SRS>
+      <SRS>EPSG:32759</SRS>
+      <SRS>EPSG:32760</SRS>
+      <SRS>EPSG:32761</SRS>
+      <SRS>EPSG:32766</SRS>
+      <SRS>EPSG:61206405</SRS>
+      <SRS>EPSG:61216405</SRS>
+      <SRS>EPSG:61226405</SRS>
+      <SRS>EPSG:61236405</SRS>
+      <SRS>EPSG:61246405</SRS>
+      <SRS>EPSG:61266405</SRS>
+      <SRS>EPSG:61266413</SRS>
+      <SRS>EPSG:61276405</SRS>
+      <SRS>EPSG:61286405</SRS>
+      <SRS>EPSG:61296405</SRS>
+      <SRS>EPSG:61306405</SRS>
+      <SRS>EPSG:61306413</SRS>
+      <SRS>EPSG:61316405</SRS>
+      <SRS>EPSG:61326405</SRS>
+      <SRS>EPSG:61336405</SRS>
+      <SRS>EPSG:61346405</SRS>
+      <SRS>EPSG:61356405</SRS>
+      <SRS>EPSG:61366405</SRS>
+      <SRS>EPSG:61376405</SRS>
+      <SRS>EPSG:61386405</SRS>
+      <SRS>EPSG:61396405</SRS>
+      <SRS>EPSG:61406405</SRS>
+      <SRS>EPSG:61406413</SRS>
+      <SRS>EPSG:61416405</SRS>
+      <SRS>EPSG:61426405</SRS>
+      <SRS>EPSG:61436405</SRS>
+      <SRS>EPSG:61446405</SRS>
+      <SRS>EPSG:61456405</SRS>
+      <SRS>EPSG:61466405</SRS>
+      <SRS>EPSG:61476405</SRS>
+      <SRS>EPSG:61486405</SRS>
+      <SRS>EPSG:61486413</SRS>
+      <SRS>EPSG:61496405</SRS>
+      <SRS>EPSG:61506405</SRS>
+      <SRS>EPSG:61516405</SRS>
+      <SRS>EPSG:61516413</SRS>
+      <SRS>EPSG:61526405</SRS>
+      <SRS>EPSG:61526413</SRS>
+      <SRS>EPSG:61536405</SRS>
+      <SRS>EPSG:61546405</SRS>
+      <SRS>EPSG:61556405</SRS>
+      <SRS>EPSG:61566405</SRS>
+      <SRS>EPSG:61576405</SRS>
+      <SRS>EPSG:61586405</SRS>
+      <SRS>EPSG:61596405</SRS>
+      <SRS>EPSG:61606405</SRS>
+      <SRS>EPSG:61616405</SRS>
+      <SRS>EPSG:61626405</SRS>
+      <SRS>EPSG:61636405</SRS>
+      <SRS>EPSG:61636413</SRS>
+      <SRS>EPSG:61646405</SRS>
+      <SRS>EPSG:61656405</SRS>
+      <SRS>EPSG:61666405</SRS>
+      <SRS>EPSG:61676405</SRS>
+      <SRS>EPSG:61676413</SRS>
+      <SRS>EPSG:61686405</SRS>
+      <SRS>EPSG:61696405</SRS>
+      <SRS>EPSG:61706405</SRS>
+      <SRS>EPSG:61706413</SRS>
+      <SRS>EPSG:61716405</SRS>
+      <SRS>EPSG:61716413</SRS>
+      <SRS>EPSG:61736405</SRS>
+      <SRS>EPSG:61736413</SRS>
+      <SRS>EPSG:61746405</SRS>
+      <SRS>EPSG:61756405</SRS>
+      <SRS>EPSG:61766405</SRS>
+      <SRS>EPSG:61766413</SRS>
+      <SRS>EPSG:61786405</SRS>
+      <SRS>EPSG:61796405</SRS>
+      <SRS>EPSG:61806405</SRS>
+      <SRS>EPSG:61806413</SRS>
+      <SRS>EPSG:61816405</SRS>
+      <SRS>EPSG:61826405</SRS>
+      <SRS>EPSG:61836405</SRS>
+      <SRS>EPSG:61846405</SRS>
+      <SRS>EPSG:61886405</SRS>
+      <SRS>EPSG:61896405</SRS>
+      <SRS>EPSG:61896413</SRS>
+      <SRS>EPSG:61906405</SRS>
+      <SRS>EPSG:61906413</SRS>
+      <SRS>EPSG:61916405</SRS>
+      <SRS>EPSG:61926405</SRS>
+      <SRS>EPSG:61936405</SRS>
+      <SRS>EPSG:61946405</SRS>
+      <SRS>EPSG:61956405</SRS>
+      <SRS>EPSG:61966405</SRS>
+      <SRS>EPSG:61976405</SRS>
+      <SRS>EPSG:61986405</SRS>
+      <SRS>EPSG:61996405</SRS>
+      <SRS>EPSG:62006405</SRS>
+      <SRS>EPSG:62016405</SRS>
+      <SRS>EPSG:62026405</SRS>
+      <SRS>EPSG:62036405</SRS>
+      <SRS>EPSG:62046405</SRS>
+      <SRS>EPSG:62056405</SRS>
+      <SRS>EPSG:62066405</SRS>
+      <SRS>EPSG:62076405</SRS>
+      <SRS>EPSG:62086405</SRS>
+      <SRS>EPSG:62096405</SRS>
+      <SRS>EPSG:62106405</SRS>
+      <SRS>EPSG:62116405</SRS>
+      <SRS>EPSG:62126405</SRS>
+      <SRS>EPSG:62136405</SRS>
+      <SRS>EPSG:62146405</SRS>
+      <SRS>EPSG:62156405</SRS>
+      <SRS>EPSG:62166405</SRS>
+      <SRS>EPSG:62186405</SRS>
+      <SRS>EPSG:62196405</SRS>
+      <SRS>EPSG:62206405</SRS>
+      <SRS>EPSG:62216405</SRS>
+      <SRS>EPSG:62226405</SRS>
+      <SRS>EPSG:62236405</SRS>
+      <SRS>EPSG:62246405</SRS>
+      <SRS>EPSG:62256405</SRS>
+      <SRS>EPSG:62276405</SRS>
+      <SRS>EPSG:62296405</SRS>
+      <SRS>EPSG:62306405</SRS>
+      <SRS>EPSG:62316405</SRS>
+      <SRS>EPSG:62326405</SRS>
+      <SRS>EPSG:62336405</SRS>
+      <SRS>EPSG:62366405</SRS>
+      <SRS>EPSG:62376405</SRS>
+      <SRS>EPSG:62386405</SRS>
+      <SRS>EPSG:62396405</SRS>
+      <SRS>EPSG:62406405</SRS>
+      <SRS>EPSG:62416405</SRS>
+      <SRS>EPSG:62426405</SRS>
+      <SRS>EPSG:62436405</SRS>
+      <SRS>EPSG:62446405</SRS>
+      <SRS>EPSG:62456405</SRS>
+      <SRS>EPSG:62466405</SRS>
+      <SRS>EPSG:62476405</SRS>
+      <SRS>EPSG:62486405</SRS>
+      <SRS>EPSG:62496405</SRS>
+      <SRS>EPSG:62506405</SRS>
+      <SRS>EPSG:62516405</SRS>
+      <SRS>EPSG:62526405</SRS>
+      <SRS>EPSG:62536405</SRS>
+      <SRS>EPSG:62546405</SRS>
+      <SRS>EPSG:62556405</SRS>
+      <SRS>EPSG:62566405</SRS>
+      <SRS>EPSG:62576405</SRS>
+      <SRS>EPSG:62586405</SRS>
+      <SRS>EPSG:62586413</SRS>
+      <SRS>EPSG:62596405</SRS>
+      <SRS>EPSG:62616405</SRS>
+      <SRS>EPSG:62626405</SRS>
+      <SRS>EPSG:62636405</SRS>
+      <SRS>EPSG:62646405</SRS>
+      <SRS>EPSG:62656405</SRS>
+      <SRS>EPSG:62666405</SRS>
+      <SRS>EPSG:62676405</SRS>
+      <SRS>EPSG:62686405</SRS>
+      <SRS>EPSG:62696405</SRS>
+      <SRS>EPSG:62706405</SRS>
+      <SRS>EPSG:62716405</SRS>
+      <SRS>EPSG:62726405</SRS>
+      <SRS>EPSG:62736405</SRS>
+      <SRS>EPSG:62746405</SRS>
+      <SRS>EPSG:62756405</SRS>
+      <SRS>EPSG:62766405</SRS>
+      <SRS>EPSG:62776405</SRS>
+      <SRS>EPSG:62786405</SRS>
+      <SRS>EPSG:62796405</SRS>
+      <SRS>EPSG:62806405</SRS>
+      <SRS>EPSG:62816405</SRS>
+      <SRS>EPSG:62826405</SRS>
+      <SRS>EPSG:62836405</SRS>
+      <SRS>EPSG:62836413</SRS>
+      <SRS>EPSG:62846405</SRS>
+      <SRS>EPSG:62856405</SRS>
+      <SRS>EPSG:62866405</SRS>
+      <SRS>EPSG:62886405</SRS>
+      <SRS>EPSG:62896405</SRS>
+      <SRS>EPSG:62926405</SRS>
+      <SRS>EPSG:62936405</SRS>
+      <SRS>EPSG:62956405</SRS>
+      <SRS>EPSG:62976405</SRS>
+      <SRS>EPSG:62986405</SRS>
+      <SRS>EPSG:62996405</SRS>
+      <SRS>EPSG:63006405</SRS>
+      <SRS>EPSG:63016405</SRS>
+      <SRS>EPSG:63026405</SRS>
+      <SRS>EPSG:63036405</SRS>
+      <SRS>EPSG:63046405</SRS>
+      <SRS>EPSG:63066405</SRS>
+      <SRS>EPSG:63076405</SRS>
+      <SRS>EPSG:63086405</SRS>
+      <SRS>EPSG:63096405</SRS>
+      <SRS>EPSG:63106405</SRS>
+      <SRS>EPSG:63116405</SRS>
+      <SRS>EPSG:63126405</SRS>
+      <SRS>EPSG:63136405</SRS>
+      <SRS>EPSG:63146405</SRS>
+      <SRS>EPSG:63156405</SRS>
+      <SRS>EPSG:63166405</SRS>
+      <SRS>EPSG:63176405</SRS>
+      <SRS>EPSG:63186405</SRS>
+      <SRS>EPSG:63196405</SRS>
+      <SRS>EPSG:63226405</SRS>
+      <SRS>EPSG:63246405</SRS>
+      <SRS>EPSG:63266405</SRS>
+      <SRS>EPSG:63266406</SRS>
+      <SRS>EPSG:63266407</SRS>
+      <SRS>EPSG:63266408</SRS>
+      <SRS>EPSG:63266409</SRS>
+      <SRS>EPSG:63266410</SRS>
+      <SRS>EPSG:63266411</SRS>
+      <SRS>EPSG:63266412</SRS>
+      <SRS>EPSG:63266413</SRS>
+      <SRS>EPSG:63266414</SRS>
+      <SRS>EPSG:63266415</SRS>
+      <SRS>EPSG:63266416</SRS>
+      <SRS>EPSG:63266417</SRS>
+      <SRS>EPSG:63266418</SRS>
+      <SRS>EPSG:63266419</SRS>
+      <SRS>EPSG:63266420</SRS>
+      <SRS>EPSG:66006405</SRS>
+      <SRS>EPSG:66016405</SRS>
+      <SRS>EPSG:66026405</SRS>
+      <SRS>EPSG:66036405</SRS>
+      <SRS>EPSG:66046405</SRS>
+      <SRS>EPSG:66056405</SRS>
+      <SRS>EPSG:66066405</SRS>
+      <SRS>EPSG:66076405</SRS>
+      <SRS>EPSG:66086405</SRS>
+      <SRS>EPSG:66096405</SRS>
+      <SRS>EPSG:66106405</SRS>
+      <SRS>EPSG:66116405</SRS>
+      <SRS>EPSG:66126405</SRS>
+      <SRS>EPSG:66126413</SRS>
+      <SRS>EPSG:66136405</SRS>
+      <SRS>EPSG:66146405</SRS>
+      <SRS>EPSG:66156405</SRS>
+      <SRS>EPSG:66166405</SRS>
+      <SRS>EPSG:66186405</SRS>
+      <SRS>EPSG:66196405</SRS>
+      <SRS>EPSG:66196413</SRS>
+      <SRS>EPSG:66206405</SRS>
+      <SRS>EPSG:66216405</SRS>
+      <SRS>EPSG:66226405</SRS>
+      <SRS>EPSG:66236405</SRS>
+      <SRS>EPSG:66246405</SRS>
+      <SRS>EPSG:66246413</SRS>
+      <SRS>EPSG:66256405</SRS>
+      <SRS>EPSG:66266405</SRS>
+      <SRS>EPSG:66276405</SRS>
+      <SRS>EPSG:66276413</SRS>
+      <SRS>EPSG:66286405</SRS>
+      <SRS>EPSG:66296405</SRS>
+      <SRS>EPSG:66306405</SRS>
+      <SRS>EPSG:66316405</SRS>
+      <SRS>EPSG:66326405</SRS>
+      <SRS>EPSG:66336405</SRS>
+      <SRS>EPSG:66346405</SRS>
+      <SRS>EPSG:66356405</SRS>
+      <SRS>EPSG:66366405</SRS>
+      <SRS>EPSG:66376405</SRS>
+      <SRS>EPSG:66386405</SRS>
+      <SRS>EPSG:66396405</SRS>
+      <SRS>EPSG:66406405</SRS>
+      <SRS>EPSG:66406413</SRS>
+      <SRS>EPSG:66416405</SRS>
+      <SRS>EPSG:66426405</SRS>
+      <SRS>EPSG:66436405</SRS>
+      <SRS>EPSG:66446405</SRS>
+      <SRS>EPSG:66456405</SRS>
+      <SRS>EPSG:66456413</SRS>
+      <SRS>EPSG:66466405</SRS>
+      <SRS>EPSG:66576405</SRS>
+      <SRS>EPSG:66586405</SRS>
+      <SRS>EPSG:66596405</SRS>
+      <SRS>EPSG:66596413</SRS>
+      <SRS>EPSG:66606405</SRS>
+      <SRS>EPSG:66616405</SRS>
+      <SRS>EPSG:66616413</SRS>
+      <SRS>EPSG:66636405</SRS>
+      <SRS>EPSG:66646405</SRS>
+      <SRS>EPSG:66656405</SRS>
+      <SRS>EPSG:66666405</SRS>
+      <SRS>EPSG:66676405</SRS>
+      <SRS>EPSG:68016405</SRS>
+      <SRS>EPSG:68026405</SRS>
+      <SRS>EPSG:68036405</SRS>
+      <SRS>EPSG:68046405</SRS>
+      <SRS>EPSG:68056405</SRS>
+      <SRS>EPSG:68066405</SRS>
+      <SRS>EPSG:68086405</SRS>
+      <SRS>EPSG:68096405</SRS>
+      <SRS>EPSG:68136405</SRS>
+      <SRS>EPSG:68146405</SRS>
+      <SRS>EPSG:68156405</SRS>
+      <SRS>EPSG:68186405</SRS>
+      <SRS>EPSG:68206405</SRS>
+      <SRS>EPSG:69036405</SRS>
+      <SRS>EPSG:42302</SRS>
+      <SRS>EPSG:42301</SRS>
+      <SRS>EPSG:900913</SRS>
+      <SRS>EPSG:45556</SRS>
+      <SRS>EPSG:45555</SRS>
+      <SRS>EPSG:54004</SRS>
+      <SRS>EPSG:41001</SRS>
+      <SRS>EPSG:42311</SRS>
+      <SRS>EPSG:42310</SRS>
+      <SRS>EPSG:18001</SRS>
+      <SRS>EPSG:100003</SRS>
+      <SRS>EPSG:42106</SRS>
+      <SRS>EPSG:100002</SRS>
+      <SRS>EPSG:42105</SRS>
+      <SRS>EPSG:100001</SRS>
+      <SRS>EPSG:42309</SRS>
+      <SRS>EPSG:42104</SRS>
+      <SRS>EPSG:42308</SRS>
+      <SRS>EPSG:42103</SRS>
+      <SRS>EPSG:42307</SRS>
+      <SRS>EPSG:42102</SRS>
+      <SRS>EPSG:42306</SRS>
+      <SRS>EPSG:42101</SRS>
+      <SRS>EPSG:42305</SRS>
+      <SRS>EPSG:42304</SRS>
+      <SRS>EPSG:42303</SRS>
+      <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>
+      <Layer queryable="1">
+        <Name>og:bugsites</Name>
+        <Title/>
+        <Abstract>Sample data from GRASS, bug sites location, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>spearfish</Keyword>
+          <Keyword>sfBugsites</Keyword>
+          <Keyword>insects</Keyword>
+          <Keyword>bugsites</Keyword>
+          <Keyword>tiger_beetles</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <LatLonBoundingBox minx="-103.8701581843142" miny="44.286540361238224" maxx="-103.63532819794625" maxy="44.52137034760618"/>
+        <BoundingBox SRS="EPSG:26713" minx="590232.0" miny="4914096.0" maxx="608471.0" maxy="4920512.0"/>
+        <Style>
+          <Name>capitals</Name>
+          <Title>Capital cities</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:bugsites"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>og:restricted</Name>
+        <Title/>
+        <Abstract>Sample data from GRASS, restricted areas, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>spearfish</Keyword>
+          <Keyword>restricted</Keyword>
+          <Keyword>sfRestricted</Keyword>
+          <Keyword>areas</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <LatLonBoundingBox minx="-104.36424600670885" miny="43.78798270975212" maxx="-103.06226503558304" maxy="45.089963680877936"/>
+        <BoundingBox SRS="EPSG:26713" minx="551796.8125" miny="4901896.0" maxx="652788.5625" maxy="4940954.0"/>
+        <Style>
+          <Name>restricted</Name>
+          <Title>Red, translucent style</Title>
+          <Abstract>A sample style that just prints out a transparent red interior with a red outline</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:restricted"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>og:archsites</Name>
+        <Title/>
+        <Abstract>Sample data from GRASS, archeological sites location, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>archsites</Keyword>
+          <Keyword>spearfish</Keyword>
+          <Keyword>sfArchsites</Keyword>
+          <Keyword>archeology</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <LatLonBoundingBox minx="-103.87480459767542" miny="44.31295793136913" maxx="-103.63549073047534" maxy="44.55227179856921"/>
+        <BoundingBox SRS="EPSG:26713" minx="589860.0" miny="4914479.0" maxx="608355.0" maxy="4926490.0"/>
+        <Style>
+          <Name>point</Name>
+          <Title>Default point</Title>
+          <Abstract>A sample style that just prints out a 6px wide red square</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:archsites"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>og:streams</Name>
+        <Title/>
+        <Abstract>Sample data from GRASS, streams, Spearfish, South Dakota, USA</Abstract>
+        <KeywordList>
+          <Keyword>spearfish</Keyword>
+          <Keyword>sfStreams</Keyword>
+          <Keyword>streams</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <LatLonBoundingBox minx="-103.88033574142051" miny="44.30711172484593" maxx="-103.62022283326024" maxy="44.5672246330062"/>
+        <BoundingBox SRS="EPSG:26713" minx="589443.0" miny="4913935.0" maxx="609526.75" maxy="4928059.5"/>
+        <Style>
+          <Name>simple_streams</Name>
+          <Title>Default Styler for streams segments</Title>
+          <Abstract>Blue lines, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:streams"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:poly_landmarks</Name>
+        <Title>Manhattan (NY) landmarks</Title>
+        <Abstract>Manhattan landmarks, identifies water, lakes, parks, interesting buildilngs</Abstract>
+        <KeywordList>
+          <Keyword>DS_poly_landmarks</Keyword>
+          <Keyword>landmarks</Keyword>
+          <Keyword>manhattan</Keyword>
+          <Keyword>poly_landmarks</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-74.0828672737" miny="40.67246384130001" maxx="-73.8660689563" maxy="40.8892621587"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.90782" maxy="40.882078"/>
+        <Style>
+          <Name>poly_landmarks</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poly_landmarks"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:poi</Name>
+        <Title>Manhattan (NY) points of interest</Title>
+        <Abstract>Points of interest in New York, New York (on Manhattan). One of the attributes contains the name of a file with a picture of the point of interest.</Abstract>
+        <KeywordList>
+          <Keyword>poi</Keyword>
+          <Keyword>Manhattan</Keyword>
+          <Keyword>DS_poi</Keyword>
+          <Keyword>points_of_interest</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-74.01244590356289" miny="40.70750285086222" maxx="-74.00795911725866" maxy="40.711989637166425"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.0118315772888" miny="40.70754683896324" maxx="-74.00153046439813" maxy="40.719885123828675"/>
+        <Style>
+          <Name>poi</Name>
+          <Title>Points of interest</Title>
+          <Abstract>Manhattan points of interest</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:poi"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tiger:tiger_roads</Name>
+        <Title>Manhattan (NY) roads</Title>
+        <Abstract>Highly simplified road layout of Manhattan in New York..</Abstract>
+        <KeywordList>
+          <Keyword>DS_tiger_roads</Keyword>
+          <Keyword>tiger_roads</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-74.06603057" miny="40.68228143" maxx="-73.86819443" maxy="40.880117569999996"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.02722" miny="40.684221" maxx="-73.907005" maxy="40.878178"/>
+        <Style>
+          <Name>tiger_roads</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tiger:tiger_roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>za:za_natural</Name>
+        <Title>Natural Landmarks in South Africa</Title>
+        <Abstract>This layer describes natural features of South Africa such as forests and lakes.</Abstract>
+        <KeywordList>
+          <Keyword>water</Keyword>
+          <Keyword>forests</Keyword>
+          <Keyword>landmarks</Keyword>
+          <Keyword>Africa</Keyword>
+          <Keyword>South</Keyword>
+          <Keyword>natural</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="16.779241142272962" miny="-36.53577846527099" maxx="32.70336002349853" maxy="-20.611659584045416"/>
+        <BoundingBox SRS="EPSG:4326" minx="16.935359954834" miny="-34.3737831115723" maxx="32.5472412109375" maxy="-22.7736549377441"/>
+        <Style>
+          <Name>za_natural</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_natural"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>za:za_points</Name>
+        <Title>Points of Interest in South Africa</Title>
+        <Abstract>Noteworthy locations such as hotels and tourist attractions in South Africa.</Abstract>
+        <KeywordList>
+          <Keyword>of</Keyword>
+          <Keyword>tourist</Keyword>
+          <Keyword>landmarks</Keyword>
+          <Keyword>zoo</Keyword>
+          <Keyword>cities</Keyword>
+          <Keyword>interest</Keyword>
+          <Keyword>attractions</Keyword>
+          <Keyword>points</Keyword>
+          <Keyword>hotel</Keyword>
+          <Keyword>museum</Keyword>
+          <Keyword>picnic</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="14.629095230102537" miny="-47.151258316040014" maxx="39.792314376831065" maxy="-21.988039169311488"/>
+        <BoundingBox SRS="EPSG:4326" minx="16.4827766418457" miny="-46.9045600891113" maxx="37.9386329650879" maxy="-22.2347373962402"/>
+        <Style>
+          <Name>za_points</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_points"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>za:za_roads</Name>
+        <Title>South African Roads</Title>
+        <Abstract>This layer describes roads in South Africa.</Abstract>
+        <KeywordList>
+          <Keyword>south</Keyword>
+          <Keyword>africa</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="16.29388177871706" miny="-36.85438787460323" maxx="33.04232465744013" maxy="-20.10594499588016"/>
+        <BoundingBox SRS="EPSG:4326" minx="16.4580821990967" miny="-34.8331336975098" maxx="32.8781242370605" maxy="-22.1271991729736"/>
+        <Style>
+          <Name>za_roads</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>za:za_vegetation</Name>
+        <Title>South African Vegetation</Title>
+        <Abstract>This layer describes vegetated areas in South Africa, categorized by biome.</Abstract>
+        <KeywordList>
+          <Keyword>south</Keyword>
+          <Keyword>vegetation</Keyword>
+          <Keyword>africa</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="16.30492322921758" miny="-36.855452365875216" maxx="33.05824930191042" maxy="-20.102126293182376"/>
+        <BoundingBox SRS="EPSG:4326" minx="16.4691715240479" miny="-34.8336486816406" maxx="32.8940010070801" maxy="-22.123929977417"/>
+        <Style>
+          <Name>za_vegetation</Name>
+          <Title>Default Styler</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=za:za_vegetation"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_cities</Name>
+        <Title>Tasmania cities</Title>
+        <Abstract>Cities in Tasmania (actually, just the capital)</Abstract>
+        <KeywordList>
+          <Keyword>cities</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="145.1667856" miny="-43.706631400000006" maxx="148.30373440000002" maxy="-40.56968259999999"/>
+        <BoundingBox SRS="EPSG:4326" minx="147.2910004483" miny="-42.851001816890005" maxx="147.2910004483" maxy="-42.851001816890005"/>
+        <Style>
+          <Name>capitals</Name>
+          <Title>Capital cities</Title>
+          <Abstract/>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_cities"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_roads</Name>
+        <Title>Tasmania roads</Title>
+        <Abstract>Main Tasmania roads</Abstract>
+        <KeywordList>
+          <Keyword>Roads</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="145.1667856" miny="-43.706631400000006" maxx="148.30373440000002" maxy="-40.56968259999999"/>
+        <BoundingBox SRS="EPSG:4326" minx="145.19754" miny="-43.423512" maxx="148.27298000000002" maxy="-40.852802"/>
+        <Style>
+          <Name>simple_roads</Name>
+          <Title>Default Styler for simple road segments</Title>
+          <Abstract>Light red line, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_state_boundaries</Name>
+        <Title>Tasmania state boundaries</Title>
+        <Abstract>Tasmania state boundaries</Abstract>
+        <KeywordList>
+          <Keyword>boundaries</Keyword>
+          <Keyword>tasmania_state_boundaries</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="143.74100879660003" miny="-44.026947203400006" maxx="148.57295620340003" maxy="-39.194999796599994"/>
+        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+        <Style>
+          <Name>green</Name>
+          <Title>Green polygon</Title>
+          <Abstract>Green fill with black outline</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_state_boundaries"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:tasmania_water_bodies</Name>
+        <Title>Tasmania water bodies</Title>
+        <Abstract>Tasmania water bodies</Abstract>
+        <KeywordList>
+          <Keyword>Lakes</Keyword>
+          <Keyword>Bodies</Keyword>
+          <Keyword>Australia</Keyword>
+          <Keyword>Water</Keyword>
+          <Keyword>Tasmania</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="145.95490063999998" miny="-43.04450786" maxx="147.23641436" maxy="-41.762994139999996"/>
+        <BoundingBox SRS="EPSG:4326" minx="145.97161899999998" miny="-43.031944" maxx="147.219696" maxy="-41.775558"/>
+        <Style>
+          <Name>cite_lakes</Name>
+          <Title>Blue lake</Title>
+          <Abstract>A blue fill, solid black outline style</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:tasmania_water_bodies"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:states</Name>
+        <Title>USA Population</Title>
+        <Abstract>This is some census data on the states.</Abstract>
+        <KeywordList>
+          <Keyword>census</Keyword>
+          <Keyword>united</Keyword>
+          <Keyword>boundaries</Keyword>
+          <Keyword>state</Keyword>
+          <Keyword>states</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-125.30903773" miny="7.705448770000002" maxx="-66.39223326999999" maxy="66.62225323"/>
+        <BoundingBox SRS="EPSG:4326" minx="-124.73142200000001" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
+        <Style>
+          <Name>population</Name>
+          <Title>Population in the United States</Title>
+          <Abstract>A sample filter that filters the United States into three
+        categories of population, drawn in different colors</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:states"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tike:waterways</Name>
+        <Title>Waterways</Title>
+        <Abstract>Waterways in Finland.</Abstract>
+        <KeywordList>
+          <Keyword>Finland</Keyword>
+          <Keyword>waterways</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="19.530168895721403" miny="58.860618000030506" maxx="31.6566005897522" maxy="70.9870496940613"/>
+        <BoundingBox SRS="EPSG:4326" minx="19.649055480957" miny="59.9357719421387" maxx="31.5377140045166" maxy="69.9118957519531"/>
+        <Style>
+          <Name>line</Name>
+          <Title>1 px blue line</Title>
+          <Abstract>Default line style, 1 pixel wide blue</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:waterways"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tike:railways</Name>
+        <Title>roads_Type</Title>
+        <Abstract>Generated from tike</Abstract>
+        <KeywordList>
+          <Keyword>tike</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>
+        <BoundingBox SRS="EPSG:4326" minx="19.5393085479736" miny="-2277.78344726562" maxx="2.971959E7" maxy="4927039.0"/>
+        <Style>
+          <Name>line</Name>
+          <Title>1 px blue line</Title>
+          <Abstract>Default line style, 1 pixel wide blue</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:railways"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tike:roads</Name>
+        <Title>roads_Type</Title>
+        <Abstract>Generated from tike</Abstract>
+        <KeywordList>
+          <Keyword>tike</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="-297176.16529836657" miny="-1.2694600326676274E7" maxx="3.0016785704606913E7" maxy="1.7619361543229006E7"/>
+        <BoundingBox SRS="EPSG:4326" minx="19.5393085479736" miny="-2277.78344726562" maxx="2.971959E7" maxy="4927039.0"/>
+        <Style>
+          <Name>line</Name>
+          <Title>1 px blue line</Title>
+          <Abstract>Default line style, 1 pixel wide blue</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>og:roads</Name>
+        <Title>roads_Type</Title>
+        <Abstract>Generated from sf_reset</Abstract>
+        <KeywordList>
+          <Keyword>roads</Keyword>
+          <Keyword>sf_reset</Keyword>
+        </KeywordList>
+        <SRS>EPSG:26713</SRS>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <LatLonBoundingBox minx="-103.88042792817339" miny="44.308776913708805" maxx="-103.62014761945467" maxy="44.56905722242751"/>
+        <BoundingBox SRS="EPSG:26713" minx="589434.8125" miny="4914006.0" maxx="609527.25" maxy="4928377.0"/>
+        <Style>
+          <Name>simple_roads</Name>
+          <Title>Default Styler for simple road segments</Title>
+          <Abstract>Light red line, 2px wide</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=og:roads"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>tike:points</Name>
+        <Title>roads_Type</Title>
+        <Abstract>Generated from tike</Abstract>
+        <KeywordList>
+          <Keyword>tike</Keyword>
+          <Keyword>roads</Keyword>
+        </KeywordList>
+        <SRS>EPSG:4326</SRS>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <LatLonBoundingBox minx="19.73377216339108" miny="59.107116584777835" maxx="31.40053188323972" maxy="70.77387630462647"/>
+        <BoundingBox SRS="EPSG:4326" minx="19.8481521606445" miny="59.8213005065918" maxx="31.2861518859863" maxy="70.0596923828125"/>
+        <Style>
+          <Name>line</Name>
+          <Title>1 px blue line</Title>
+          <Abstract>Default line style, 1 pixel wide blue</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=tike:points"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>topp:bluemarble</Name>
+        <Title>Blue Marble Imagery</Title>
+        <Abstract>Blue Marble NG global bathymetry and topography data from NASA.  More information about the Blue Marble NG project is available from http://earthobservatory.nasa.gov/Features/BlueMarble .</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>bluemarble</Keyword>
+          <Keyword>bluemarble</Keyword>
+        </KeywordList>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-180.00000003333" miny="-89.99999996486703" maxx="179.99999993067" maxy="90.000000033333"/>
+        <BoundingBox SRS="EPSG:4326" minx="-180.00000003333" miny="-89.99999996486703" maxx="179.99999993067" maxy="90.000000033333"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=topp:bluemarble"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:Arc_Sample</Name>
+        <Title>Global annual rainfall</Title>
+        <Abstract>Global annual rainfall in ArcGrid format</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>arcGridSample</Keyword>
+          <Keyword>arcGridSample_Coverage</Keyword>
+        </KeywordList>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
+        <BoundingBox SRS="EPSG:4326" minx="-180.0" miny="-90.0" maxx="180.0" maxy="90.0"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Arc_Sample"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>nurc:Img_Sample</Name>
+        <Title>North America sample imagery</Title>
+        <Abstract>A very rough imagery of North America</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>worldImageSample</Keyword>
+          <Keyword>worldImageSample_Coverage</Keyword>
+        </KeywordList>
+        <!--WKT definition of this CRS:
+GEOGCS["WGS 84", 
+  DATUM["World Geodetic System 1984", 
+    SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], 
+    AUTHORITY["EPSG","6326"]], 
+  PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+  UNIT["degree", 0.017453292519943295], 
+  AXIS["Geodetic longitude", EAST], 
+  AXIS["Geodetic latitude", NORTH], 
+  AUTHORITY["EPSG","4326"]]-->
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>
+        <BoundingBox SRS="EPSG:4326" minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>
+        <Style>
+          <Name>raster</Name>
+          <Title>Raster</Title>
+          <Abstract>A sample style for rasters, good for displaying imagery</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=nurc:Img_Sample"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="1">
+        <Name>sf:sfdem</Name>
+        <Title>Spearfish DEM</Title>
+        <Abstract>Digital Elevation Model data for Spearfish, South Dakota</Abstract>
+        <KeywordList>
+          <Keyword>WCS</Keyword>
+          <Keyword>sf</Keyword>
+          <Keyword>dem</Keyword>
+          <Keyword>digital</Keyword>
+          <Keyword>elevation</Keyword>
+          <Keyword>model</Keyword>
+        </KeywordList>
+        <!--WKT definition of this CRS:
+PROJCS["NAD27 / UTM zone 13N", 
+  GEOGCS["NAD27", 
+    DATUM["North American Datum 1927", 
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]], 
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0], 
+      AUTHORITY["EPSG","6267"]], 
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], 
+    UNIT["degree", 0.017453292519943295], 
+    AXIS["Geodetic longitude", EAST], 
+    AXIS["Geodetic latitude", NORTH], 
+    AUTHORITY["EPSG","4267"]], 
+  PROJECTION["Transverse Mercator", AUTHORITY["EPSG","9807"]], 
+  PARAMETER["central_meridian", -105.0], 
+  PARAMETER["latitude_of_origin", 0.0], 
+  PARAMETER["scale_factor", 0.9996], 
+  PARAMETER["false_easting", 500000.0], 
+  PARAMETER["false_northing", 0.0], 
+  UNIT["m", 1.0], 
+  AXIS["Easting", EAST], 
+  AXIS["Northing", NORTH], 
+  AUTHORITY["EPSG","26713"]]-->
+        <SRS>EPSG:26713</SRS>
+        <LatLonBoundingBox minx="-103.87108701853181" miny="44.370187074132616" maxx="-103.62940739432703" maxy="44.5016011535299"/>
+        <BoundingBox SRS="EPSG:26713" minx="589980.0" miny="4913700.0" maxx="609000.0" maxy="4928010.0"/>
+        <Style>
+          <Name>dem</Name>
+          <Title>Simple DEM style</Title>
+          <Abstract>Classic elevation color progression</Abstract>
+          <LegendURL width="20" height="20">
+            <Format>image/png</Format>
+            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://demo.opengeo.org/geoserver/wms/GetLegendGraphic?VERSION=1.0.0&amp;FORMAT=image/png&amp;WIDTH=20&amp;HEIGHT=20&amp;LAYER=sf:sfdem"/>
+          </LegendURL>
+        </Style>
+      </Layer>
+      <Layer queryable="0">
+        <Name>tasmania</Name>
+        <Title>tasmania</Title>
+        <Abstract>Layer-Group type layer: tasmania</Abstract>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+        <BoundingBox SRS="EPSG:4326" minx="143.83482400000003" miny="-43.648056" maxx="148.47914100000003" maxy="-39.573891"/>
+      </Layer>
+      <Layer queryable="0">
+        <Name>tiger-ny</Name>
+        <Title>tiger-ny</Title>
+        <Abstract>Layer-Group type layer: tiger-ny</Abstract>
+        <SRS>EPSG:4326</SRS>
+        <LatLonBoundingBox minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>
+        <BoundingBox SRS="EPSG:4326" minx="-74.047185" miny="40.679648" maxx="-73.907005" maxy="40.882078"/>
+      </Layer>
+    </Layer>
+  </Capability>
+</WMT_MS_Capabilities>

Modified: sandbox/ahocevar/playground/tests/throws.js
===================================================================
--- sandbox/ahocevar/playground/tests/throws.js	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tests/throws.js	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,7 +2,7 @@
 
   throws.js -- Adds a `throws_` method to AnotherWay test objects.
 
-  Copyright 2005 MetaCarta, Inc., released under the BSD License.
+  Copyright 2005 OpenLayers Contributors. released under the BSD License.
 
 
   A reference to this file needs to be added to `run-tests.html` in the
@@ -79,4 +79,4 @@
     } else {
         this.fail(doc);
     }
-};
\ No newline at end of file
+};

Modified: sandbox/ahocevar/playground/theme/default/google.css
===================================================================
--- sandbox/ahocevar/playground/theme/default/google.css	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/theme/default/google.css	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,6 +1,7 @@
 .olLayerGoogleCopyright {
     right: 3px;
-    bottom: 2px;  
+    bottom: 2px;
+    left: auto;  
 }
 .olLayerGooglePoweredBy {
     left: 2px;


Property changes on: sandbox/ahocevar/playground/theme/default/ie6-style.css
___________________________________________________________________
Deleted: svn:executable
   - *


Property changes on: sandbox/ahocevar/playground/theme/default/img/pan-panel-NOALPHA.png
___________________________________________________________________
Deleted: svn:executable
   - *


Property changes on: sandbox/ahocevar/playground/theme/default/img/pan-panel.png
___________________________________________________________________
Deleted: svn:executable
   - *


Property changes on: sandbox/ahocevar/playground/theme/default/img/zoom-panel-NOALPHA.png
___________________________________________________________________
Deleted: svn:executable
   - *


Property changes on: sandbox/ahocevar/playground/theme/default/img/zoom-panel.png
___________________________________________________________________
Deleted: svn:executable
   - *

Modified: sandbox/ahocevar/playground/theme/default/style.css
===================================================================
--- sandbox/ahocevar/playground/theme/default/style.css	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/theme/default/style.css	2010-11-28 15:48:59 UTC (rev 10920)
@@ -1,5 +1,5 @@
 div.olMap {
-	z-index: 0;
+    z-index: 0;
     padding: 0px!important;
     margin: 0px!important;
     cursor: default;
@@ -11,6 +11,7 @@
 
 div.olLayerDiv {
    -moz-user-select: none;
+   -khtml-user-select: none;
 }
 
 .olLayerGoogleCopyright {
@@ -36,6 +37,8 @@
     font-size: smaller;
 }
 .olControlScaleLine {
+   display: block;
+   position: absolute;
    left: 10px;
    bottom: 15px;
    font-size: xx-small;
@@ -214,12 +217,12 @@
 .olControlEditingToolbar .olControlDrawFeaturePolygonItemActive { 
   background-position: -26px -23px ;                                                                   
 }
-.olControlSaveFeaturesItemActive { 
+div.olControlSaveFeaturesItemActive { 
     background-image: url(img/save_features_on.png);
     background-repeat: no-repeat;
     background-position: 0px 1px;
 }
-.olControlSaveFeaturesItemInactive { 
+div.olControlSaveFeaturesItemInactive { 
     background-image: url(img/save_features_off.png);
     background-repeat: no-repeat;
     background-position: 0px 1px;
@@ -320,8 +323,15 @@
 
 .olControlNoSelect {
  -moz-user-select: none;
+ -khtml-user-select: none;
 }
 
+.olImageLoadError {
+    background-color: pink;
+    opacity: 0.5;
+    filter: alpha(opacity=50); /* IE */
+}
+
 /**
  * Cursor styles
  */
@@ -341,3 +351,49 @@
 .olControlDragFeatureActive.olControlDragFeatureOver.olDragDown {
     cursor: -moz-grabbing;
 }
+
+/**
+ * Layer switcher
+ */
+.olControlLayerSwitcher {
+    position: absolute;
+    top: 25px;
+    right: 0px;
+    width: 20em;
+    font-family: sans-serif;
+    font-weight: bold;
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+    font-size: smaller;
+    color: white;
+    background-color: transparent;
+}
+
+.olControlLayerSwitcher .layersDiv {
+    padding-top: 5px;
+    padding-left: 10px;
+    padding-bottom: 5px;
+    padding-right: 75px;
+    background-color: darkblue;
+    width: 100%;
+    height: 100%;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLbl,
+.olControlLayerSwitcher .layersDiv .dataLbl {
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLayersDiv,
+.olControlLayerSwitcher .layersDiv .dataLayersDiv {
+    padding-left: 10px;
+}
+
+.olControlLayerSwitcher .maximizeDiv,
+.olControlLayerSwitcher .minimizeDiv {
+    top: 5px;
+    right: 0px;
+}

Modified: sandbox/ahocevar/playground/tools/exampleparser.py
===================================================================
--- sandbox/ahocevar/playground/tools/exampleparser.py	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tools/exampleparser.py	2010-11-28 15:48:59 UTC (rev 10920)
@@ -135,6 +135,10 @@
         title = doc.createElementNS(atomuri, "title")
         title.appendChild(doc.createTextNode(example["title"] or example["example"]))
         entry.appendChild(title)
+              
+        tags = doc.createElementNS(atomuri, "tags")
+        tags.appendChild(doc.createTextNode(example["tags"] or example["example"]))
+        entry.appendChild(tags)
         
         link = doc.createElementNS(atomuri, "link")
         link.setAttribute("href", "%s%s" % (feedPath, example["example"]))
@@ -171,7 +175,7 @@
     """
     index = {}
     unword = re.compile("\\W+")
-    keys = ["shortdesc", "title"]
+    keys = ["shortdesc", "title", "tags"]
     for i in range(len(examples)):
         for key in keys:
             text = examples[i][key]
@@ -204,7 +208,7 @@
     print 'Reading examples from %s and writing out to %s' % (examplesLocation, outFile.name)
    
     exampleList = []
-    docIds = ['title','shortdesc']
+    docIds = ['title','shortdesc','tags']
    
     #comment out option to create docs from online resource
     #examplesLocation = 'http://svn.openlayers.org/sandbox/docs/examples/'

Modified: sandbox/ahocevar/playground/tools/mergejs.py
===================================================================
--- sandbox/ahocevar/playground/tools/mergejs.py	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tools/mergejs.py	2010-11-28 15:48:59 UTC (rev 10920)
@@ -31,7 +31,7 @@
 #
 # Note: This is a very rough initial version of this code.
 #
-# -- Copyright 2005-2008 MetaCarta, Inc. / OpenLayers project --
+# -- Copyright 2005-2010 OpenLayers contributors / OpenLayers project --
 #
 
 # TODO: Allow files to be excluded. e.g. `Crossbrowser/DebugMode.js`?
@@ -94,6 +94,7 @@
 
         [exclude]
         3rd/logger.js
+        exclude/this/dir
 
     All headings are required.
 
@@ -122,6 +123,20 @@
         self.include =  lines[lines.index("[include]") + 1:lines.index("[exclude]")]
         self.exclude =  lines[lines.index("[exclude]") + 1:]
 
+def undesired(filepath, excludes):
+    # exclude file if listed
+    exclude = filepath in excludes
+    if not exclude:
+        # check if directory is listed
+        for excludepath in excludes:
+            if not excludepath.endswith("/"):
+                excludepath += "/"
+            if filepath.startswith(excludepath):
+                exclude = True
+                break
+    return exclude
+            
+
 def run (sourceDirectory, outputFilename = None, configFile = None):
     cfg = None
     if configFile:
@@ -138,7 +153,7 @@
                 if cfg and cfg.include:
                     if filepath in cfg.include or filepath in cfg.forceFirst:
                         allFiles.append(filepath)
-                elif (not cfg) or (filepath not in cfg.exclude):
+                elif (not cfg) or (not undesired(filepath, cfg.exclude)):
                     allFiles.append(filepath)
 
     ## Header inserted at the start of each file in the output

Copied: sandbox/ahocevar/playground/tools/mkrelease.sh (from rev 10919, trunk/openlayers/tools/mkrelease.sh)
===================================================================
--- sandbox/ahocevar/playground/tools/mkrelease.sh	                        (rev 0)
+++ sandbox/ahocevar/playground/tools/mkrelease.sh	2010-11-28 15:48:59 UTC (rev 10920)
@@ -0,0 +1,28 @@
+#!/bin/sh -x
+
+svn export http://svn.openlayers.org/tags/openlayers/release-$VERSION OpenLayers-$VERSION
+cd OpenLayers-$VERSION/build
+./build.py
+mkdir /osgeo/openlayers/docs/api/$VERSION
+cd ..
+cp build/OpenLayers.js /osgeo/openlayers/docs/api/$VERSION
+cp -a img/ /osgeo/openlayers/docs/api/$VERSION
+cp -a theme/ /osgeo/openlayers/docs/api/$VERSION
+
+
+# First remove all .pyc files from the directory.
+  rm tools/*.pyc
+  # move single file version
+  cp build/OpenLayers.js OpenLayers.js
+  rm build/OpenLayers.js
+  
+  cd ..
+  mkdir OpenLayers-$VERSION/doc/devdocs
+  naturaldocs -i OpenLayers-$VERSION/lib -o HTML OpenLayers-$VERSION/doc/devdocs -p OpenLayers-$VERSION/doc_config -s Default OL
+  mkdir OpenLayers-$VERSION/doc/apidocs
+  naturaldocs -i OpenLayers-$VERSION/lib -o HTML OpenLayers-$VERSION/doc/apidocs -p OpenLayers-$VERSION/apidoc_config -s Default OL
+
+  tar cvfz OpenLayers-$VERSION.tar.gz OpenLayers-$VERSION/
+  cp OpenLayers-$VERSION.tar.gz /osgeo/openlayers/docs/download
+  zip -9r OpenLayers-$VERSION.zip OpenLayers-$VERSION/
+

Modified: sandbox/ahocevar/playground/tools/update_dev_dir.sh
===================================================================
--- sandbox/ahocevar/playground/tools/update_dev_dir.sh	2010-11-25 16:46:57 UTC (rev 10919)
+++ sandbox/ahocevar/playground/tools/update_dev_dir.sh	2010-11-28 15:48:59 UTC (rev 10920)
@@ -2,10 +2,10 @@
 
 # Used to update http://openlayers.org/dev/ 
 
-svn up /www/openlayers/docs/dev; 
+svn up /osgeo/openlayers/docs/dev; 
 
 # Get current 'Last Changed Rev'
-REV=`svn info /www/openlayers/docs/dev/ | grep 'Last Changed Rev' | awk '{print $4}'`
+REV=`svn info /osgeo/openlayers/docs/dev/ | grep 'Revision' | awk '{print $2}'`
 
 # Get the last svn rev
 touch /tmp/ol_svn_rev
@@ -14,32 +14,33 @@
 # If they're not equal, do some work.
 if [ ! o$REV = $OLD_REV ]; then
 
-    cd /www/openlayers/docs/dev/tools/ 
+    cd /osgeo/openlayers/docs/dev/tools/ 
     python exampleparser.py
-    cd /www/openlayers/docs/dev/build
+    cd /osgeo/openlayers/docs/dev/build
     ./build.py
     
     cp OpenLayers.js ..
     cd ..
     
     sed -i -e 's!../lib/OpenLayers.js!../OpenLayers.js!' examples/*.html
-    perl /home/crschmidt/NaturalDocs -i /www/openlayers/docs/dev/lib -o HTML /www/openlayers/dev/apidocs -p /www/openlayers/docs/dev/apidoc_config -s Default OL >/dev/null
-    perl /home/crschmidt/NaturalDocs -i /www/openlayers/docs/dev/lib -o HTML /www/openlayers/dev/docs -p /www/openlayers/docs/dev/doc_config -s Default OL >/dev/null
-
+    naturaldocs -i /osgeo/openlayers/docs/dev/lib -o HTML /osgeo/openlayers/dev/apidocs -p /osgeo/openlayers/docs/dev/apidoc_config -s Default OL >/dev/null
+    naturaldocs -i /osgeo/openlayers/docs/dev/lib -o HTML /osgeo/openlayers/dev/docs -p /osgeo/openlayers/docs/dev/doc_config -s Default OL >/dev/null
+    
+    svn up /osgeo/openlayers/dev/sandbox/
     # Record the revision
     echo -n $REV > /tmp/ol_svn_rev
 fi    
    
-svn up /www/openlayers/documentation-checkout
-REV=`svn info /www/openlayers/documentation-checkout | grep 'Last Changed Rev' | awk '{print $4}'`
+svn up /osgeo/openlayers/documentation-checkout
+REV=`svn info /osgeo/openlayers/documentation-checkout | grep 'Last Changed Rev' | awk '{print $4}'`
 # Get the last svn rev
 touch /tmp/ol_doc_rev
 OLD_REV="o`cat /tmp/ol_doc_rev`"
 # If they're not equal, do some work.
 if [ ! o$REV = $OLD_REV ]; then
-    cd /www/openlayers/documentation-checkout
+    cd /osgeo/openlayers/documentation-checkout
     make html > /dev/null
-    cp -r _build/html/*  /www/openlayers/documentation
+    cp -r _build/html/*  /osgeo/openlayers/documentation
     
     echo -n $REV > /tmp/ol_doc_rev
 fi    



More information about the Commits mailing list