[OpenLayers-Commits] r10921 - in addins: . timedpointtrack timedpointtrack/trunk timedpointtrack/trunk/examples timedpointtrack/trunk/examples/xml timedpointtrack/trunk/img timedpointtrack/trunk/lib timedpointtrack/trunk/lib/OpenLayers timedpointtrack/trunk/lib/OpenLayers/Control timedpointtrack/trunk/lib/OpenLayers/Layer timedpointtrack/trunk/tests timedpointtrack/trunk/tests/Control timedpointtrack/trunk/theme timedpointtrack/trunk/theme/default

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Mon Nov 29 03:56:27 EST 2010


Author: ahocevar
Date: 2010-11-29 00:56:27 -0800 (Mon, 29 Nov 2010)
New Revision: 10921

Added:
   addins/timedpointtrack/
   addins/timedpointtrack/trunk/
   addins/timedpointtrack/trunk/INSTALL.txt
   addins/timedpointtrack/trunk/examples/
   addins/timedpointtrack/trunk/examples/time-select-control.html
   addins/timedpointtrack/trunk/examples/timed-point-track-markers.html
   addins/timedpointtrack/trunk/examples/xml/
   addins/timedpointtrack/trunk/examples/xml/8_short.xml
   addins/timedpointtrack/trunk/examples/xml/track1.xml
   addins/timedpointtrack/trunk/img/
   addins/timedpointtrack/trunk/img/time-minus-mini.png
   addins/timedpointtrack/trunk/img/time-plus-mini.png
   addins/timedpointtrack/trunk/img/time-world-mini.png
   addins/timedpointtrack/trunk/img/timebar.png
   addins/timedpointtrack/trunk/lib/
   addins/timedpointtrack/trunk/lib/OpenLayers/
   addins/timedpointtrack/trunk/lib/OpenLayers/Control/
   addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeDisplay.js
   addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSlider.js
   addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSliderBar.js
   addins/timedpointtrack/trunk/lib/OpenLayers/Layer/
   addins/timedpointtrack/trunk/lib/OpenLayers/Layer/TimedPointTrack.js
   addins/timedpointtrack/trunk/lib/TimedPointTrack.js
   addins/timedpointtrack/trunk/tests/
   addins/timedpointtrack/trunk/tests/BaseTypes.html
   addins/timedpointtrack/trunk/tests/Control/
   addins/timedpointtrack/trunk/tests/Control/TimeSlider.html
   addins/timedpointtrack/trunk/tests/Control/TimeSliderBar.html
   addins/timedpointtrack/trunk/tests/Layer.html
   addins/timedpointtrack/trunk/tests/Map.html
   addins/timedpointtrack/trunk/tests/list-tests.html
   addins/timedpointtrack/trunk/tests/run-tests.html
   addins/timedpointtrack/trunk/theme/
   addins/timedpointtrack/trunk/theme/default/
   addins/timedpointtrack/trunk/theme/default/timedpointtrack.css
Log:
added timedpointtrack addin (closes #2951)


Added: addins/timedpointtrack/trunk/INSTALL.txt
===================================================================
--- addins/timedpointtrack/trunk/INSTALL.txt	                        (rev 0)
+++ addins/timedpointtrack/trunk/INSTALL.txt	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,16 @@
+For using the addin in development mode, copy the addins folder from the
+sandbox into the OpenLayers directory that also contains the lib, theme, img
+and other folders. Add a script tag for
+addins/timedpointtrack/trunk/lib/TimedPointTrack.js to your application's html.
+
+For creating a single file build, copy the content of the
+addins/timedpointtrack/trunk folder to the OpenLayers directory that also contains
+the lib, theme and other folders. Add TimedPointTrack.js to the include
+section of your build profile and do the build as usual. You do not need to
+include an extra script tag in your html, because all required js is already
+included in the OpenLayers single file build. You may, however, need to change
+the OpenLayers.TimedPointTrackImgPath property (only if you also need to
+change OpenLayers.ImgPath, and both locations are the same).
+
+In both cases, add addins/timedpointtrack/trunk/theme/default/timedpointtrack.css
+to as css resource to your html page.
\ No newline at end of file

Added: addins/timedpointtrack/trunk/examples/time-select-control.html
===================================================================
--- addins/timedpointtrack/trunk/examples/time-select-control.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/examples/time-select-control.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,105 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../../../../examples/style.css" type="text/css" />
+    <link rel="stylesheet" href="../../../../theme/default/style.css" type="text/css" />
+    <link rel="stylesheet" href="../theme/default/timedpointtrack.css" type="text/css" />
+    <style type="text/css">
+        #map {
+            width: 800px;
+            height: 400px;
+            border: 1px solid black;
+        }
+    </style>
+    <script src="../../../../lib/OpenLayers.js"></script>
+    <script src="../lib/TimedPointTrack.js"></script>
+<!--<script src="http://www.javascripttoolbox.com/libsource.php/date/source/date.js"></script>-->
+    <script type="text/javascript">
+        var map, layer, rss, popup, timeBar, timepos;
+
+        OpenLayers.ProxyHost = "proxy.cgi?url=";
+        function init(){
+            map = new OpenLayers.Map('map', {maxResolution:'auto'});
+            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+            map.addLayer(layer);
+            map.setCenter(new OpenLayers.LonLat(20.22, 22.05), 9);
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+            timeBar = new OpenLayers.Control.TimeSliderBar( {continuous: true} );
+            map.addControl(timeBar);
+            timepos = new OpenLayers.Control.TimeDisplay();
+            if (Date.$VERSION){      // to use Date formatting functions from javascripttoolbox just uncomment the <script> statement above
+                timepos.formatOutput = function (d) {
+                    if (d) return d.format('MMM d, yyyy, hhmm');
+                }
+            }
+            map.addControl(timepos);
+            map.addControl(new OpenLayers.Control.MousePosition());
+        }
+
+        function addUrl() {
+            var urlObj = OpenLayers.Util.getElement('url'); 
+            var value = urlObj.value;
+            var parts = value.split("/");
+            rss = new OpenLayers.Layer.TimedPointTrack(parts[parts.length-1], value, {
+                styleMap: new OpenLayers.StyleMap({
+                    "default": OpenLayers.Util.applyDefaults({
+                        cursor: "pointer",
+                        pointRadius: 10,
+                        graphicOpacity: 1,
+                        externalGraphic: "../../../../img/marker.png",
+                        graphicYOffset: -19
+                    }, OpenLayers.Feature.Vector.style["default"]),
+                    "select": {
+                        externalGraphic: "../../../../img/marker-gold.png",
+                        strokeColor: "yellow",
+                        strokeWidth: 2
+                    }
+                })
+            });
+            map.addLayer(rss);
+
+            // SelectFeature control for popups
+            var selectFeature = new OpenLayers.Control.SelectFeature(rss, {
+                onSelect: function(feature) {
+                    popup = new OpenLayers.Popup.FramedCloud("event", 
+                         feature.geometry.getBounds().getCenterLonLat(),
+                         new OpenLayers.Size(100,100),
+                         "<h2>"+feature.attributes.title + "</h2>" + feature.attributes.description,
+                         null, true, OpenLayers.Function.bind(
+                             function(){this.unselect(feature);}, this));
+                    feature.popup = popup;
+                    map.addPopup(popup);
+                },
+                onUnselect: function(feature) {
+                    map.removePopup(feature.popup);
+                    feature.popup.destroy();
+                    feature.popup = null;
+                }
+            });
+            map.addControl(selectFeature);
+            selectFeature.activate();
+            
+            rss.events.register("loadend", null, function() {
+                timeBar.rangeFromTrack(rss.features[0].geometry);
+            });
+        }
+
+        function setTime() {
+            var targetdate = OpenLayers.Date.smartParse(OpenLayers.Util.getElement('date').value);
+            map.setTime(targetdate);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1>Select time in time-aware layers</h1>
+    <p style="font-size:.9em;">This demo uses OpenLayers.Control.TimeSliderBar with OpenLayers.Layer.GeoRSS and OpenLayers.Layer.TimedPointTrack. The track is created by connecting the points of the GeoRSS feed, and the points can be tracked based on their temporal attribute.</a></p>
+    <form onsubmit="return false;">
+   Load GeoRSS URL: <input type="text" id="url" size="50" /><input type="submit" onclick="addUrl(); return false;" value="Load Feed" onsubmit="addUrl(); return false;" />
+    </form> <form onsubmit="return false;">
+    Selected time: <input type="text" id="date" value="1995-12-12T09:20:00Z" > <input type="submit" onSubmit="setTime(); return false;" onClick="setTime(); 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 -- for example, entering 'xml/track1.xml' will work by default.</p>
+    <p>The example shows a track, displayed as a line connecting the points of the feed. The time-select control in the lower right can be used to select a certain time for the displayed layers, either roughly by dragging the bar, or step by step pressing the + and - icons.</p>
+    <div id="map"></div>
+  </body>
+</html>

Added: addins/timedpointtrack/trunk/examples/timed-point-track-markers.html
===================================================================
--- addins/timedpointtrack/trunk/examples/timed-point-track-markers.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/examples/timed-point-track-markers.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,93 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../../../../examples/style.css" type="text/css" />
+    <link rel="stylesheet" href="../../../../theme/default/timedpointtrack.css" type="text/css" />
+    <style type="text/css">
+        #map {
+            width: 800px;
+            height: 400px;
+            border: 1px solid black;
+        }
+    </style>
+    <script src="../../../../lib/OpenLayers.js"></script>
+    <script src="../lib/TimedPointTrack.js"></script>
+    <script type="text/javascript">
+        var map, layer, rss, popup;
+
+        OpenLayers.ProxyHost = "proxy.cgi?url=";
+        function init(){
+            map = new OpenLayers.Map('map', {maxResolution:'auto'});
+            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
+                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );
+            map.addLayer(layer);
+            map.setCenter(new OpenLayers.LonLat(20.22, 22.05), 9);
+            map.addControl(new OpenLayers.Control.LayerSwitcher());
+        }
+
+        function addUrl() {
+            var urlObj = OpenLayers.Util.getElement('url'); 
+            var value = urlObj.value;
+            var parts = value.split("/");
+            rss = new OpenLayers.Layer.TimedPointTrack(parts[parts.length-1], value, {
+                styleMap: new OpenLayers.StyleMap({
+                    "default": OpenLayers.Util.applyDefaults({
+                        cursor: "pointer",
+                        pointRadius: 10,
+                        graphicOpacity: 1,
+                        externalGraphic: "../../../../img/marker.png",
+                        graphicYOffset: -19
+                    }, OpenLayers.Feature.Vector.style["default"]),
+                    "select": {
+                        externalGraphic: "../../../../img/marker-gold.png",
+                        strokeColor: "yellow",
+                        strokeWidth: 2
+                    }
+                })
+            });
+            map.addLayer(rss);
+
+            // SelectFeature control for popups
+            var selectFeature = new OpenLayers.Control.SelectFeature(rss, {
+                onSelect: function(feature) {
+                    popup = new OpenLayers.Popup.FramedCloud("event", 
+                         feature.geometry.getBounds().getCenterLonLat(),
+                         new OpenLayers.Size(100,100),
+                         "<h2>"+feature.attributes.title + "</h2>" + feature.attributes.description,
+                         null, true, OpenLayers.Function.bind(
+                             function(){this.unselect(feature);}, this));
+                    feature.popup = popup;
+                    map.addPopup(popup);
+                },
+                onUnselect: function(feature) {
+                    map.removePopup(feature.popup);
+                    feature.popup.destroy();
+                    feature.popup = null;
+                }
+            });
+            map.addControl(selectFeature);
+            selectFeature.activate();
+        }
+
+        function setTime() {
+            var targetdate = OpenLayers.Date.smartParse(OpenLayers.Util.getElement('date').value);
+            rss.permanentHighlight = OpenLayers.Util.getElement('phighlight').checked;
+            rss.interpolatePoints = OpenLayers.Util.getElement('ipoints').checked;
+            map.setTime(targetdate);
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1>GeoRSS TimedPointTrack in OpenLayers</h1>
+    <p style="font-size:.9em;">This demo uses OpenLayers.Layer.GeoRSS and OpenLayers.Layer.TimedPointTrack. The track is created by connecting the points of the GeoRSS feed.</a></p>
+    <form onsubmit="return false;">
+   Load GeoRSS URL: <input type="text" id="url" size="50" value="xml/track1.xml" /><input type="submit" onclick="addUrl(); return false;" value="Load Feed" onsubmit="addUrl(); return false;" />
+    </form> <form onsubmit="return false;">
+    <input type="checkbox" id="phighlight"> permanentHighlight <BR>
+    <input type="checkbox" id="ipoints"> interpolatePoints <BR>
+    Selected time: <input type="text" id="date" value="1995-12-12T09:20:00Z" > <input type="submit" onSubmit="setTime(); return false;" onClick="setTime(); 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 -- for example, entering 'xml/track1.xml' will work by default.</p>
+    <p>The example shows a track, displayed as a line connecting the points of the feed. It also shows markers at positions that have a title tag in the rss item. If clicked, a popup will show title and description.</p>   
+    <div id="map"></div>
+  </body>
+</html>

Added: addins/timedpointtrack/trunk/examples/xml/8_short.xml
===================================================================
--- addins/timedpointtrack/trunk/examples/xml/8_short.xml	                        (rev 0)
+++ addins/timedpointtrack/trunk/examples/xml/8_short.xml	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,1495 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+  <id>8</id>
+  <author>
+    <name>Ian Mayo</name>
+  </author>
+  <updated>2003-01-24T14:01:48.000Z</updated>
+  <title type="text">Dataset id:8</title>
+  <category scheme="cats/platforms.xml" term="5" label="Helo_1"></category>
+  <category scheme="cats/formats.xml" term="2" label="data.pos"></category>
+  <category scheme="cats/exercises.xml" term="2" label="Ferry demo ran on:15 May 2009 09:10:03 GMT"></category>
+  <category scheme="cats/platformColor" term="0000FF"></category>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>1928</id>
+    <updated>2003-01-24T13:00:18.000Z</updated>
+    <title type="text">Observation:1928</title>
+    <georss:point>25.7 52.8</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>1944</id>
+    <updated>2003-01-24T13:00:33.000Z</updated>
+    <title type="text">Observation:1944</title>
+    <georss:point>25.700234614738967 52.80745607040254</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>1960</id>
+    <updated>2003-01-24T13:00:48.000Z</updated>
+    <title type="text">Observation:1960</title>
+    <georss:point>25.70042850083176 52.8136177930885</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>1976</id>
+    <updated>2003-01-24T13:01:03.000Z</updated>
+    <title type="text">Observation:1976</title>
+    <georss:point>25.70062238692455 52.81977952580955</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>1992</id>
+    <updated>2003-01-24T13:01:18.000Z</updated>
+    <title type="text">Observation:1992</title>
+    <georss:point>25.70081627301734 52.8259412685658</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2008</id>
+    <updated>2003-01-24T13:01:33.000Z</updated>
+    <title type="text">Observation:2008</title>
+    <georss:point>25.701010159110133 52.83210302135735</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2024</id>
+    <updated>2003-01-24T13:01:48.000Z</updated>
+    <title type="text">Observation:2024</title>
+    <georss:point>25.701204045202925 52.8382647841843</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2040</id>
+    <updated>2003-01-24T13:02:03.000Z</updated>
+    <title type="text">Observation:2040</title>
+    <georss:point>25.701397931295716 52.844426557046745</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2056</id>
+    <updated>2003-01-24T13:02:18.000Z</updated>
+    <title type="text">Observation:2056</title>
+    <georss:point>25.701591817388508 52.85058833994481</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2072</id>
+    <updated>2003-01-24T13:02:33.000Z</updated>
+    <title type="text">Observation:2072</title>
+    <georss:point>25.7017857034813 52.85675013287858</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2088</id>
+    <updated>2003-01-24T13:02:48.000Z</updated>
+    <title type="text">Observation:2088</title>
+    <georss:point>25.70197958957409 52.86291193584817</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2104</id>
+    <updated>2003-01-24T13:03:03.000Z</updated>
+    <title type="text">Observation:2104</title>
+    <georss:point>25.702173475666882 52.86907374885368</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2120</id>
+    <updated>2003-01-24T13:03:18.000Z</updated>
+    <title type="text">Observation:2120</title>
+    <georss:point>25.702367361759674 52.87523557189521</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2136</id>
+    <updated>2003-01-24T13:03:33.000Z</updated>
+    <title type="text">Observation:2136</title>
+    <georss:point>25.702561247852465 52.881397404972866</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2152</id>
+    <updated>2003-01-24T13:03:48.000Z</updated>
+    <title type="text">Observation:2152</title>
+    <georss:point>25.702755133945256 52.887559248086745</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2168</id>
+    <updated>2003-01-24T13:04:03.000Z</updated>
+    <title type="text">Observation:2168</title>
+    <georss:point>25.702949020038048 52.893721101236956</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2184</id>
+    <updated>2003-01-24T13:04:18.000Z</updated>
+    <title type="text">Observation:2184</title>
+    <georss:point>25.70314290613084 52.899882964423604</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2200</id>
+    <updated>2003-01-24T13:04:33.000Z</updated>
+    <title type="text">Observation:2200</title>
+    <georss:point>25.70333679222363 52.906044837646796</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2216</id>
+    <updated>2003-01-24T13:04:48.000Z</updated>
+    <title type="text">Observation:2216</title>
+    <georss:point>25.703530678316422 52.912206720906624</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2232</id>
+    <updated>2003-01-24T13:05:03.000Z</updated>
+    <title type="text">Observation:2232</title>
+    <georss:point>25.703724564409214 52.918368614203196</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2248</id>
+    <updated>2003-01-24T13:05:18.000Z</updated>
+    <title type="text">Observation:2248</title>
+    <georss:point>25.703918450502005 52.92453051753661</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2264</id>
+    <updated>2003-01-24T13:05:33.000Z</updated>
+    <title type="text">Observation:2264</title>
+    <georss:point>25.704112336594797 52.93069243090698</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2280</id>
+    <updated>2003-01-24T13:05:48.000Z</updated>
+    <title type="text">Observation:2280</title>
+    <georss:point>25.70430622268759 52.9368543543144</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2296</id>
+    <updated>2003-01-24T13:06:03.000Z</updated>
+    <title type="text">Observation:2296</title>
+    <georss:point>25.70450010878038 52.94301628775898</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2312</id>
+    <updated>2003-01-24T13:06:18.000Z</updated>
+    <title type="text">Observation:2312</title>
+    <georss:point>25.70469399487317 52.94917823124082</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2328</id>
+    <updated>2003-01-24T13:06:33.000Z</updated>
+    <title type="text">Observation:2328</title>
+    <georss:point>25.704887880965963 52.955340184760026</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2344</id>
+    <updated>2003-01-24T13:06:48.000Z</updated>
+    <title type="text">Observation:2344</title>
+    <georss:point>25.705081767058754 52.9615021483167</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2360</id>
+    <updated>2003-01-24T13:07:03.000Z</updated>
+    <title type="text">Observation:2360</title>
+    <georss:point>25.705275653151546 52.96766412191094</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2376</id>
+    <updated>2003-01-24T13:07:18.000Z</updated>
+    <title type="text">Observation:2376</title>
+    <georss:point>25.705469539244337 52.97382610554286</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2392</id>
+    <updated>2003-01-24T13:07:33.000Z</updated>
+    <title type="text">Observation:2392</title>
+    <georss:point>25.70566342533713 52.979988099212555</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2408</id>
+    <updated>2003-01-24T13:07:48.000Z</updated>
+    <title type="text">Observation:2408</title>
+    <georss:point>25.70585731142992 52.98615010292013</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2424</id>
+    <updated>2003-01-24T13:08:03.000Z</updated>
+    <title type="text">Observation:2424</title>
+    <georss:point>25.70605119752271 52.99231211666569</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2440</id>
+    <updated>2003-01-24T13:08:18.000Z</updated>
+    <title type="text">Observation:2440</title>
+    <georss:point>25.706245083615503 52.998474140449325</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2456</id>
+    <updated>2003-01-24T13:08:33.000Z</updated>
+    <title type="text">Observation:2456</title>
+    <georss:point>25.706438969708294 53.00463617427116</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2472</id>
+    <updated>2003-01-24T13:08:48.000Z</updated>
+    <title type="text">Observation:2472</title>
+    <georss:point>25.706632855801086 53.01079821813129</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2488</id>
+    <updated>2003-01-24T13:09:03.000Z</updated>
+    <title type="text">Observation:2488</title>
+    <georss:point>25.706826741893877 53.01696027202982</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2504</id>
+    <updated>2003-01-24T13:09:18.000Z</updated>
+    <title type="text">Observation:2504</title>
+    <georss:point>25.70702062798667 53.023122335966846</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2520</id>
+    <updated>2003-01-24T13:09:33.000Z</updated>
+    <title type="text">Observation:2520</title>
+    <georss:point>25.70721451407946 53.02928440994247</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2536</id>
+    <updated>2003-01-24T13:09:48.000Z</updated>
+    <title type="text">Observation:2536</title>
+    <georss:point>25.707408400172252 53.035446493956805</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2552</id>
+    <updated>2003-01-24T13:10:03.000Z</updated>
+    <title type="text">Observation:2552</title>
+    <georss:point>25.707602286265043 53.04160858800995</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2568</id>
+    <updated>2003-01-24T13:10:18.000Z</updated>
+    <title type="text">Observation:2568</title>
+    <georss:point>25.707796172357835 53.047770692102006</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2584</id>
+    <updated>2003-01-24T13:10:33.000Z</updated>
+    <title type="text">Observation:2584</title>
+    <georss:point>25.707990058450626 53.05393280623308</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2602</id>
+    <updated>2003-01-24T13:10:48.000Z</updated>
+    <title type="text">Observation:2602</title>
+    <georss:point>25.705499434455344 53.0591315270714</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2620</id>
+    <updated>2003-01-24T13:11:03.000Z</updated>
+    <title type="text">Observation:2620</title>
+    <georss:point>25.700498033008 53.061812713672396</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2638</id>
+    <updated>2003-01-24T13:11:18.000Z</updated>
+    <title type="text">Observation:2638</title>
+    <georss:point>25.695483090834667 53.0644656197206</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2656</id>
+    <updated>2003-01-24T13:11:33.000Z</updated>
+    <title type="text">Observation:2656</title>
+    <georss:point>25.690471130079167 53.06712534377127</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2674</id>
+    <updated>2003-01-24T13:11:48.000Z</updated>
+    <title type="text">Observation:2674</title>
+    <georss:point>25.685462216114747 53.06979201443536</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2692</id>
+    <updated>2003-01-24T13:12:03.000Z</updated>
+    <title type="text">Observation:2692</title>
+    <georss:point>25.680456415408834 53.072465761534495</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2710</id>
+    <updated>2003-01-24T13:12:18.000Z</updated>
+    <title type="text">Observation:2710</title>
+    <georss:point>25.67545379939895 53.07514672496084</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2728</id>
+    <updated>2003-01-24T13:12:33.000Z</updated>
+    <title type="text">Observation:2728</title>
+    <georss:point>25.670454440679475 53.07783504577904</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2746</id>
+    <updated>2003-01-24T13:12:48.000Z</updated>
+    <title type="text">Observation:2746</title>
+    <georss:point>25.665458414959765 53.080530870643805</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2764</id>
+    <updated>2003-01-24T13:13:03.000Z</updated>
+    <title type="text">Observation:2764</title>
+    <georss:point>25.66046580305055 53.0832343562011</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2782</id>
+    <updated>2003-01-24T13:13:18.000Z</updated>
+    <title type="text">Observation:2782</title>
+    <georss:point>25.65547668767334 53.085945661679766</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2800</id>
+    <updated>2003-01-24T13:13:33.000Z</updated>
+    <title type="text">Observation:2800</title>
+    <georss:point>25.65049115544638 53.08866495329256</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2818</id>
+    <updated>2003-01-24T13:13:48.000Z</updated>
+    <title type="text">Observation:2818</title>
+    <georss:point>25.645509298246292 53.09139240714768</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2836</id>
+    <updated>2003-01-24T13:14:03.000Z</updated>
+    <title type="text">Observation:2836</title>
+    <georss:point>25.64053121065103 53.09412820332365</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2854</id>
+    <updated>2003-01-24T13:14:18.000Z</updated>
+    <title type="text">Observation:2854</title>
+    <georss:point>25.63555699327442 53.09687253319057</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2872</id>
+    <updated>2003-01-24T13:14:33.000Z</updated>
+    <title type="text">Observation:2872</title>
+    <georss:point>25.630586751527836 53.09962559642259</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2890</id>
+    <updated>2003-01-24T13:14:48.000Z</updated>
+    <title type="text">Observation:2890</title>
+    <georss:point>25.625620595690222 53.10238760095418</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2908</id>
+    <updated>2003-01-24T13:15:03.000Z</updated>
+    <title type="text">Observation:2908</title>
+    <georss:point>25.620658641646404 53.10515876439988</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2926</id>
+    <updated>2003-01-24T13:15:18.000Z</updated>
+    <title type="text">Observation:2926</title>
+    <georss:point>25.615701011639754 53.10793931546522</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2944</id>
+    <updated>2003-01-24T13:15:33.000Z</updated>
+    <title type="text">Observation:2944</title>
+    <georss:point>25.61074783504018 53.11072949534807</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2962</id>
+    <updated>2003-01-24T13:15:48.000Z</updated>
+    <title type="text">Observation:2962</title>
+    <georss:point>25.605799248456048 53.11352955766831</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2980</id>
+    <updated>2003-01-24T13:16:03.000Z</updated>
+    <title type="text">Observation:2980</title>
+    <georss:point>25.60085539652622 53.1163397698536</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>2998</id>
+    <updated>2003-01-24T13:16:18.000Z</updated>
+    <title type="text">Observation:2998</title>
+    <georss:point>25.595916431375315 53.11916041159672</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3016</id>
+    <updated>2003-01-24T13:16:33.000Z</updated>
+    <title type="text">Observation:3016</title>
+    <georss:point>25.59098251614263 53.121991782057385</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3034</id>
+    <updated>2003-01-24T13:16:48.000Z</updated>
+    <title type="text">Observation:3034</title>
+    <georss:point>25.58605382243946 53.12483419392167</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3052</id>
+    <updated>2003-01-24T13:17:03.000Z</updated>
+    <title type="text">Observation:3052</title>
+    <georss:point>25.581130534616193 53.12768798202367</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3070</id>
+    <updated>2003-01-24T13:17:18.000Z</updated>
+    <title type="text">Observation:3070</title>
+    <georss:point>25.576212847927106 53.13055349884254</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3088</id>
+    <updated>2003-01-24T13:17:33.000Z</updated>
+    <title type="text">Observation:3088</title>
+    <georss:point>25.571300971502957 53.13343112016767</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3106</id>
+    <updated>2003-01-24T13:17:48.000Z</updated>
+    <title type="text">Observation:3106</title>
+    <georss:point>25.566395130006452 53.136321247822075</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3124</id>
+    <updated>2003-01-24T13:18:03.000Z</updated>
+    <title type="text">Observation:3124</title>
+    <georss:point>25.56149556463695 53.13922431090837</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3142</id>
+    <updated>2003-01-24T13:18:18.000Z</updated>
+    <title type="text">Observation:3142</title>
+    <georss:point>25.556602533469057 53.142140765586326</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3160</id>
+    <updated>2003-01-24T13:18:33.000Z</updated>
+    <title type="text">Observation:3160</title>
+    <georss:point>25.551716316740173 53.14507110493106</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3178</id>
+    <updated>2003-01-24T13:18:48.000Z</updated>
+    <title type="text">Observation:3178</title>
+    <georss:point>25.546837216621533 53.14801585717677</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3196</id>
+    <updated>2003-01-24T13:19:03.000Z</updated>
+    <title type="text">Observation:3196</title>
+    <georss:point>25.541965561270317 53.150975592574454</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3214</id>
+    <updated>2003-01-24T13:19:18.000Z</updated>
+    <title type="text">Observation:3214</title>
+    <georss:point>25.53710170757909 53.15395092729323</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3232</id>
+    <updated>2003-01-24T13:19:33.000Z</updated>
+    <title type="text">Observation:3232</title>
+    <georss:point>25.532246046183477 53.15694253155008</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3250</id>
+    <updated>2003-01-24T13:19:48.000Z</updated>
+    <title type="text">Observation:3250</title>
+    <georss:point>25.527399005197477 53.159951134759964</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3268</id>
+    <updated>2003-01-24T13:20:03.000Z</updated>
+    <title type="text">Observation:3268</title>
+    <georss:point>25.52256105555414 53.162977533434585</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3286</id>
+    <updated>2003-01-24T13:20:18.000Z</updated>
+    <title type="text">Observation:3286</title>
+    <georss:point>25.51773271875432 53.1660226032059</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3304</id>
+    <updated>2003-01-24T13:20:33.000Z</updated>
+    <title type="text">Observation:3304</title>
+    <georss:point>25.512914573451752 53.169087307789155</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3322</id>
+    <updated>2003-01-24T13:20:48.000Z</updated>
+    <title type="text">Observation:3322</title>
+    <georss:point>25.508107268270592 53.17217271907714</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3340</id>
+    <updated>2003-01-24T13:21:03.000Z</updated>
+    <title type="text">Observation:3340</title>
+    <georss:point>25.503311530691605 53.17528002835514</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3358</id>
+    <updated>2003-01-24T13:21:18.000Z</updated>
+    <title type="text">Observation:3358</title>
+    <georss:point>25.498528185431194 53.17841057410805</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3376</id>
+    <updated>2003-01-24T13:21:33.000Z</updated>
+    <title type="text">Observation:3376</title>
+    <georss:point>25.493758172947604 53.18156586777974</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3394</id>
+    <updated>2003-01-24T13:21:48.000Z</updated>
+    <title type="text">Observation:3394</title>
+    <georss:point>25.48900257582977 53.18474763141872</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3412</id>
+    <updated>2003-01-24T13:22:03.000Z</updated>
+    <title type="text">Observation:3412</title>
+    <georss:point>25.484262652062625 53.18795784401507</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3430</id>
+    <updated>2003-01-24T13:22:18.000Z</updated>
+    <title type="text">Observation:3430</title>
+    <georss:point>25.47953988042415 53.19119880443806</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3448</id>
+    <updated>2003-01-24T13:22:33.000Z</updated>
+    <title type="text">Observation:3448</title>
+    <georss:point>25.474836021393802 53.19447321435165</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3468</id>
+    <updated>2003-01-24T13:22:48.000Z</updated>
+    <title type="text">Observation:3468</title>
+    <georss:point>25.470153206180946 53.19778429929142</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3488</id>
+    <updated>2003-01-24T13:23:03.000Z</updated>
+    <title type="text">Observation:3488</title>
+    <georss:point>25.46549405982312 53.201135971246394</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3508</id>
+    <updated>2003-01-24T13:23:18.000Z</updated>
+    <title type="text">Observation:3508</title>
+    <georss:point>25.460861893310863 53.204533081463076</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3528</id>
+    <updated>2003-01-24T13:23:33.000Z</updated>
+    <title type="text">Observation:3528</title>
+    <georss:point>25.456260850442963 53.207981554544176</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3548</id>
+    <updated>2003-01-24T13:23:48.000Z</updated>
+    <title type="text">Observation:3548</title>
+    <georss:point>25.451696828897973 53.2114897209113</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3570</id>
+    <updated>2003-01-24T13:24:03.000Z</updated>
+    <title type="text">Observation:3570</title>
+    <georss:point>25.44717796845891 53.215068740279996</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3592</id>
+    <updated>2003-01-24T13:24:18.000Z</updated>
+    <title type="text">Observation:3592</title>
+    <georss:point>25.442716559531082 53.218734953666164</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3614</id>
+    <updated>2003-01-24T13:24:33.000Z</updated>
+    <title type="text">Observation:3614</title>
+    <georss:point>25.438333129500037 53.22251461445059</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3636</id>
+    <updated>2003-01-24T13:24:48.000Z</updated>
+    <title type="text">Observation:3636</title>
+    <georss:point>25.434068298353953 53.22645697052954</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3658</id>
+    <updated>2003-01-24T13:25:03.000Z</updated>
+    <title type="text">Observation:3658</title>
+    <georss:point>25.430036308710317 53.2306886573663</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3680</id>
+    <updated>2003-01-24T13:25:18.000Z</updated>
+    <title type="text">Observation:3680</title>
+    <georss:point>25.42758120555809 53.23614357760095</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3702</id>
+    <updated>2003-01-24T13:25:33.000Z</updated>
+    <title type="text">Observation:3702</title>
+    <georss:point>25.428390056977534 53.24194912784279</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3724</id>
+    <updated>2003-01-24T13:25:48.000Z</updated>
+    <title type="text">Observation:3724</title>
+    <georss:point>25.43333517640754 53.244076329828296</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3746</id>
+    <updated>2003-01-24T13:26:03.000Z</updated>
+    <title type="text">Observation:3746</title>
+    <georss:point>25.437471444418104 53.24039770433283</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3768</id>
+    <updated>2003-01-24T13:26:18.000Z</updated>
+    <title type="text">Observation:3768</title>
+    <georss:point>25.436662592998662 53.234591716500404</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3790</id>
+    <updated>2003-01-24T13:26:33.000Z</updated>
+    <title type="text">Observation:3790</title>
+    <georss:point>25.431746487771495 53.23209055127772</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3812</id>
+    <updated>2003-01-24T13:26:48.000Z</updated>
+    <title type="text">Observation:3812</title>
+    <georss:point>25.426708272561143 53.23393048479024</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3834</id>
+    <updated>2003-01-24T13:27:03.000Z</updated>
+    <title type="text">Observation:3834</title>
+    <georss:point>25.425628216916838 53.23968160140132</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3856</id>
+    <updated>2003-01-24T13:27:18.000Z</updated>
+    <title type="text">Observation:3856</title>
+    <georss:point>25.42958637648289 53.24359287790649</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3878</id>
+    <updated>2003-01-24T13:27:33.000Z</updated>
+    <title type="text">Observation:3878</title>
+    <georss:point>25.434624591693243 53.24175290044655</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3900</id>
+    <updated>2003-01-24T13:27:48.000Z</updated>
+    <title type="text">Observation:3900</title>
+    <georss:point>25.43570497619472 53.236001237395016</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3922</id>
+    <updated>2003-01-24T13:28:03.000Z</updated>
+    <title type="text">Observation:3922</title>
+    <georss:point>25.431787818629733 53.23203798064087</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3944</id>
+    <updated>2003-01-24T13:28:18.000Z</updated>
+    <title type="text">Observation:3944</title>
+    <georss:point>25.42669010298942 53.23366461124412</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3966</id>
+    <updated>2003-01-24T13:28:33.000Z</updated>
+    <title type="text">Observation:3966</title>
+    <georss:point>25.42541346816991 53.23936612882089</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>3988</id>
+    <updated>2003-01-24T13:28:48.000Z</updated>
+    <title type="text">Observation:3988</title>
+    <georss:point>25.429234548990713 53.243441101828104</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4010</id>
+    <updated>2003-01-24T13:29:03.000Z</updated>
+    <title type="text">Observation:4010</title>
+    <georss:point>25.434332264631028 53.241814436876695</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4032</id>
+    <updated>2003-01-24T13:29:18.000Z</updated>
+    <title type="text">Observation:4032</title>
+    <georss:point>25.435863985632828 53.236091765397944</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4054</id>
+    <updated>2003-01-24T13:29:33.000Z</updated>
+    <title type="text">Observation:4054</title>
+    <georss:point>25.433352116100725 53.230917423650304</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4076</id>
+    <updated>2003-01-24T13:29:48.000Z</updated>
+    <title type="text">Observation:4076</title>
+    <georss:point>25.428049396992044 53.23073907324208</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4098</id>
+    <updated>2003-01-24T13:30:03.000Z</updated>
+    <title type="text">Observation:4098</title>
+    <georss:point>25.425258547415464 53.2357347290242</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4120</id>
+    <updated>2003-01-24T13:30:18.000Z</updated>
+    <title type="text">Observation:4120</title>
+    <georss:point>25.427770416947567 53.24090872323713</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4142</id>
+    <updated>2003-01-24T13:30:33.000Z</updated>
+    <title type="text">Observation:4142</title>
+    <georss:point>25.433119604191536 53.24123234746897</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4164</id>
+    <updated>2003-01-24T13:30:48.000Z</updated>
+    <title type="text">Observation:4164</title>
+    <georss:point>25.437814947733365 53.23800314955152</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4186</id>
+    <updated>2003-01-24T13:31:03.000Z</updated>
+    <title type="text">Observation:4186</title>
+    <georss:point>25.44309844884763 53.23747277429097</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4208</id>
+    <updated>2003-01-24T13:31:18.000Z</updated>
+    <title type="text">Observation:4208</title>
+    <georss:point>25.44615497875234 53.242274733049506</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4230</id>
+    <updated>2003-01-24T13:31:33.000Z</updated>
+    <title type="text">Observation:4230</title>
+    <georss:point>25.44392800754279 53.247607103799915</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4252</id>
+    <updated>2003-01-24T13:31:48.000Z</updated>
+    <title type="text">Observation:4252</title>
+    <georss:point>25.438644506428528 53.24813748271347</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4274</id>
+    <updated>2003-01-24T13:32:03.000Z</updated>
+    <title type="text">Observation:4274</title>
+    <georss:point>25.435584854358503 53.24333621701369</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4296</id>
+    <updated>2003-01-24T13:32:18.000Z</updated>
+    <title type="text">Observation:4296</title>
+    <georss:point>25.437620828526576 53.23789261884447</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4318</id>
+    <updated>2003-01-24T13:32:33.000Z</updated>
+    <title type="text">Observation:4318</title>
+    <georss:point>25.442772014520603 53.23648748941458</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4340</id>
+    <updated>2003-01-24T13:32:48.000Z</updated>
+    <title type="text">Observation:4340</title>
+    <georss:point>25.446446489707252 53.240725156648935</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4362</id>
+    <updated>2003-01-24T13:33:03.000Z</updated>
+    <title type="text">Observation:4362</title>
+    <georss:point>25.444969778899882 53.246368056293065</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4384</id>
+    <updated>2003-01-24T13:33:18.000Z</updated>
+    <title type="text">Observation:4384</title>
+    <georss:point>25.439818592905855 53.24777321136359</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4406</id>
+    <updated>2003-01-24T13:33:33.000Z</updated>
+    <title type="text">Observation:4406</title>
+    <georss:point>25.436144117719206 53.24353577732358</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4428</id>
+    <updated>2003-01-24T13:33:48.000Z</updated>
+    <title type="text">Observation:4428</title>
+    <georss:point>25.437620828526576 53.23789329116566</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4450</id>
+    <updated>2003-01-24T13:34:03.000Z</updated>
+    <title type="text">Observation:4450</title>
+    <georss:point>25.442772014520603 53.23648816173578</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4472</id>
+    <updated>2003-01-24T13:34:18.000Z</updated>
+    <title type="text">Observation:4472</title>
+    <georss:point>25.446446489707252 53.24072582897013</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4494</id>
+    <updated>2003-01-24T13:34:33.000Z</updated>
+    <title type="text">Observation:4494</title>
+    <georss:point>25.444969778899882 53.246368728614264</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4516</id>
+    <updated>2003-01-24T13:34:48.000Z</updated>
+    <title type="text">Observation:4516</title>
+    <georss:point>25.439818592905855 53.247773883684786</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4538</id>
+    <updated>2003-01-24T13:35:03.000Z</updated>
+    <title type="text">Observation:4538</title>
+    <georss:point>25.436144117719206 53.24353644964478</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4560</id>
+    <updated>2003-01-24T13:35:18.000Z</updated>
+    <title type="text">Observation:4560</title>
+    <georss:point>25.437620828526576 53.23789396348687</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4582</id>
+    <updated>2003-01-24T13:35:33.000Z</updated>
+    <title type="text">Observation:4582</title>
+    <georss:point>25.442772014520603 53.236488834056985</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4604</id>
+    <updated>2003-01-24T13:35:48.000Z</updated>
+    <title type="text">Observation:4604</title>
+    <georss:point>25.446446489707252 53.240726501291334</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4626</id>
+    <updated>2003-01-24T13:36:03.000Z</updated>
+    <title type="text">Observation:4626</title>
+    <georss:point>25.44497999040912 53.246380088297094</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4648</id>
+    <updated>2003-01-24T13:36:18.000Z</updated>
+    <title type="text">Observation:4648</title>
+    <georss:point>25.439934715571855 53.24819634866241</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4670</id>
+    <updated>2003-01-24T13:36:33.000Z</updated>
+    <title type="text">Observation:4670</title>
+    <georss:point>25.435991697469095 53.244266028622725</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4692</id>
+    <updated>2003-01-24T13:36:48.000Z</updated>
+    <title type="text">Observation:4692</title>
+    <georss:point>25.4370939542036 53.23851958374266</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4714</id>
+    <updated>2003-01-24T13:37:03.000Z</updated>
+    <title type="text">Observation:4714</title>
+    <georss:point>25.442139229040862 53.23670336621544</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4736</id>
+    <updated>2003-01-24T13:37:18.000Z</updated>
+    <title type="text">Observation:4736</title>
+    <georss:point>25.44608224714362 53.24063388686952</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4758</id>
+    <updated>2003-01-24T13:37:33.000Z</updated>
+    <title type="text">Observation:4758</title>
+    <georss:point>25.445486171942193 53.24663558954488</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4780</id>
+    <updated>2003-01-24T13:37:48.000Z</updated>
+    <title type="text">Observation:4780</title>
+    <georss:point>25.442345279263474 53.251651119841576</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4802</id>
+    <updated>2003-01-24T13:38:03.000Z</updated>
+    <title type="text">Observation:4802</title>
+    <georss:point>25.43737909628982 53.25371743483338</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4824</id>
+    <updated>2003-01-24T13:38:18.000Z</updated>
+    <title type="text">Observation:4824</title>
+    <georss:point>25.433280037622126 53.24998809029759</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4846</id>
+    <updated>2003-01-24T13:38:33.000Z</updated>
+    <title type="text">Observation:4846</title>
+    <georss:point>25.434147161928085 53.244192586254535</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4868</id>
+    <updated>2003-01-24T13:38:48.000Z</updated>
+    <title type="text">Observation:4868</title>
+    <georss:point>25.439113344901738 53.24212632670244</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4890</id>
+    <updated>2003-01-24T13:39:03.000Z</updated>
+    <title type="text">Observation:4890</title>
+    <georss:point>25.443658039224545 53.24546570651659</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4912</id>
+    <updated>2003-01-24T13:39:18.000Z</updated>
+    <title type="text">Observation:4912</title>
+    <georss:point>25.4470254436209 53.250351929963905</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4934</id>
+    <updated>2003-01-24T13:39:33.000Z</updated>
+    <title type="text">Observation:4934</title>
+    <georss:point>25.44761488930484 53.25619072238444</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4956</id>
+    <updated>2003-01-24T13:39:48.000Z</updated>
+    <title type="text">Observation:4956</title>
+    <georss:point>25.44334365164931 53.25967538739087</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>4978</id>
+    <updated>2003-01-24T13:40:03.000Z</updated>
+    <title type="text">Observation:4978</title>
+    <georss:point>25.438482968309838 53.25732143848942</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5000</id>
+    <updated>2003-01-24T13:40:18.000Z</updated>
+    <title type="text">Observation:5000</title>
+    <georss:point>25.437893522625895 53.25148308878425</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5022</id>
+    <updated>2003-01-24T13:40:33.000Z</updated>
+    <title type="text">Observation:5022</title>
+    <georss:point>25.442164760281425 53.247998581471336</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5044</id>
+    <updated>2003-01-24T13:40:48.000Z</updated>
+    <title type="text">Observation:5044</title>
+    <georss:point>25.447337923980328 53.24988641747608</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5066</id>
+    <updated>2003-01-24T13:41:03.000Z</updated>
+    <title type="text">Observation:5066</title>
+    <georss:point>25.450881968499093 53.254525179315834</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5088</id>
+    <updated>2003-01-24T13:41:18.000Z</updated>
+    <title type="text">Observation:5088</title>
+    <georss:point>25.45121310265861 53.26038907449864</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5110</id>
+    <updated>2003-01-24T13:41:33.000Z</updated>
+    <title type="text">Observation:5110</title>
+    <georss:point>25.446793220736165 53.26363855892874</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5132</id>
+    <updated>2003-01-24T13:41:48.000Z</updated>
+    <title type="text">Observation:5132</title>
+    <georss:point>25.442042204654204 53.261024347304065</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5154</id>
+    <updated>2003-01-24T13:42:03.000Z</updated>
+    <title type="text">Observation:5154</title>
+    <georss:point>25.441711070494687 53.255160898712134</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5176</id>
+    <updated>2003-01-24T13:42:18.000Z</updated>
+    <title type="text">Observation:5176</title>
+    <georss:point>25.446126271311606 53.251874221826455</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5198</id>
+    <updated>2003-01-24T13:42:33.000Z</updated>
+    <title type="text">Observation:5198</title>
+    <georss:point>25.45142573967588 53.25332016165435</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5220</id>
+    <updated>2003-01-24T13:42:48.000Z</updated>
+    <title type="text">Observation:5220</title>
+    <georss:point>25.45463440033145 53.25799915410828</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5242</id>
+    <updated>2003-01-24T13:43:03.000Z</updated>
+    <title type="text">Observation:5242</title>
+    <georss:point>25.452579912199194 53.26341616549109</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5264</id>
+    <updated>2003-01-24T13:43:18.000Z</updated>
+    <title type="text">Observation:5264</title>
+    <georss:point>25.44731676341137 53.264154139559004</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5286</id>
+    <updated>2003-01-24T13:43:33.000Z</updated>
+    <title type="text">Observation:5286</title>
+    <georss:point>25.4441081027558 53.25947543148252</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5308</id>
+    <updated>2003-01-24T13:43:48.000Z</updated>
+    <title type="text">Observation:5308</title>
+    <georss:point>25.446162590888054 53.25405880125838</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5330</id>
+    <updated>2003-01-24T13:44:03.000Z</updated>
+    <title type="text">Observation:5330</title>
+    <georss:point>25.451442462746723 53.25326102772147</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5352</id>
+    <updated>2003-01-24T13:44:18.000Z</updated>
+    <title type="text">Observation:5352</title>
+    <georss:point>25.455259289290943 53.25736227662947</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5374</id>
+    <updated>2003-01-24T13:44:33.000Z</updated>
+    <title type="text">Observation:5374</title>
+    <georss:point>25.454484238706858 53.26317477460904</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5396</id>
+    <updated>2003-01-24T13:44:48.000Z</updated>
+    <title type="text">Observation:5396</title>
+    <georss:point>25.44955160039427 53.265337594775616</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5418</id>
+    <updated>2003-01-24T13:45:03.000Z</updated>
+    <title type="text">Observation:5418</title>
+    <georss:point>25.445394012665762 53.26168819253767</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5440</id>
+    <updated>2003-01-24T13:45:18.000Z</updated>
+    <title type="text">Observation:5440</title>
+    <georss:point>25.446169063249844 53.255876133417004</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5462</id>
+    <updated>2003-01-24T13:45:33.000Z</updated>
+    <title type="text">Observation:5462</title>
+    <georss:point>25.451101701562436 53.253713374016435</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5484</id>
+    <updated>2003-01-24T13:45:48.000Z</updated>
+    <title type="text">Observation:5484</title>
+    <georss:point>25.455465115837164 53.25721349074816</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5506</id>
+    <updated>2003-01-24T13:46:03.000Z</updated>
+    <title type="text">Observation:5506</title>
+    <georss:point>25.456301864174762 53.263015535365504</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5528</id>
+    <updated>2003-01-24T13:46:18.000Z</updated>
+    <title type="text">Observation:5528</title>
+    <georss:point>25.452183337519195 53.2667190679052</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5550</id>
+    <updated>2003-01-24T13:46:33.000Z</updated>
+    <title type="text">Observation:5550</title>
+    <georss:point>25.44722806252603 53.26462071400623</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5572</id>
+    <updated>2003-01-24T13:46:48.000Z</updated>
+    <title type="text">Observation:5572</title>
+    <georss:point>25.446391314188432 53.2588191066871</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5594</id>
+    <updated>2003-01-24T13:47:03.000Z</updated>
+    <title type="text">Observation:5594</title>
+    <georss:point>25.450509840844 53.25511575232773</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5616</id>
+    <updated>2003-01-24T13:47:18.000Z</updated>
+    <title type="text">Observation:5616</title>
+    <georss:point>25.455554141541707 53.25710617511388</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5638</id>
+    <updated>2003-01-24T13:47:33.000Z</updated>
+    <title type="text">Observation:5638</title>
+    <georss:point>25.457979706342794 53.26249166786528</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5660</id>
+    <updated>2003-01-24T13:47:48.000Z</updated>
+    <title type="text">Observation:5660</title>
+    <georss:point>25.45666224847232 53.2681832658464</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5682</id>
+    <updated>2003-01-24T13:48:03.000Z</updated>
+    <title type="text">Observation:5682</title>
+    <georss:point>25.451553035462837 53.26976537794254</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5704</id>
+    <updated>2003-01-24T13:48:18.000Z</updated>
+    <title type="text">Observation:5704</title>
+    <georss:point>25.447761280323824 53.26565619592151</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5726</id>
+    <updated>2003-01-24T13:48:33.000Z</updated>
+    <title type="text">Observation:5726</title>
+    <georss:point>25.4490787381943 53.25996501877252</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5748</id>
+    <updated>2003-01-24T13:48:48.000Z</updated>
+    <title type="text">Observation:5748</title>
+    <georss:point>25.45418987672917 53.25837302091971</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5770</id>
+    <updated>2003-01-24T13:49:03.000Z</updated>
+    <title type="text">Observation:5770</title>
+    <georss:point>25.458755972167765 53.2617230405531</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5792</id>
+    <updated>2003-01-24T13:49:18.000Z</updated>
+    <title type="text">Observation:5792</title>
+    <georss:point>25.46048784135775 53.267276903965936</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5814</id>
+    <updated>2003-01-24T13:49:33.000Z</updated>
+    <title type="text">Observation:5814</title>
+    <georss:point>25.45701107497788 53.27171496408418</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5836</id>
+    <updated>2003-01-24T13:49:48.000Z</updated>
+    <title type="text">Observation:5836</title>
+    <georss:point>25.451802439408027 53.270599241310784</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5858</id>
+    <updated>2003-01-24T13:50:03.000Z</updated>
+    <title type="text">Observation:5858</title>
+    <georss:point>25.450070570218042 53.26504577864469</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5880</id>
+    <updated>2003-01-24T13:50:18.000Z</updated>
+    <title type="text">Observation:5880</title>
+    <georss:point>25.45354733659791 53.2606079744276</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5902</id>
+    <updated>2003-01-24T13:50:33.000Z</updated>
+    <title type="text">Observation:5902</title>
+    <georss:point>25.458846320368206 53.26155804925423</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5924</id>
+    <updated>2003-01-24T13:50:48.000Z</updated>
+    <title type="text">Observation:5924</title>
+    <georss:point>25.462253999579836 53.26625530570244</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5946</id>
+    <updated>2003-01-24T13:51:03.000Z</updated>
+    <title type="text">Observation:5946</title>
+    <georss:point>25.462108379794415 53.27212898657643</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5968</id>
+    <updated>2003-01-24T13:51:18.000Z</updated>
+    <title type="text">Observation:5968</title>
+    <georss:point>25.457442893548635 53.27492609369269</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>5990</id>
+    <updated>2003-01-24T13:51:33.000Z</updated>
+    <title type="text">Observation:5990</title>
+    <georss:point>25.452923027088275 53.27184975474805</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6012</id>
+    <updated>2003-01-24T13:51:48.000Z</updated>
+    <title type="text">Observation:6012</title>
+    <georss:point>25.453068646873696 53.265976522139496</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6034</id>
+    <updated>2003-01-24T13:52:03.000Z</updated>
+    <title type="text">Observation:6034</title>
+    <georss:point>25.457734149959965 53.26317800225537</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6056</id>
+    <updated>2003-01-24T13:52:18.000Z</updated>
+    <title type="text">Observation:6056</title>
+    <georss:point>25.462703009753806 53.26567132006267</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6078</id>
+    <updated>2003-01-24T13:52:33.000Z</updated>
+    <title type="text">Observation:6078</title>
+    <georss:point>25.465066056252475 53.27093219991394</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6100</id>
+    <updated>2003-01-24T13:52:48.000Z</updated>
+    <title type="text">Observation:6100</title>
+    <georss:point>25.462134115224668 53.275829276798994</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6122</id>
+    <updated>2003-01-24T13:53:03.000Z</updated>
+    <title type="text">Observation:6122</title>
+    <georss:point>25.456839127698192 53.27546549870588</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6144</id>
+    <updated>2003-01-24T13:53:18.000Z</updated>
+    <title type="text">Observation:6144</title>
+    <georss:point>25.454476081199523 53.2702049784959</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6166</id>
+    <updated>2003-01-24T13:53:33.000Z</updated>
+    <title type="text">Observation:6166</title>
+    <georss:point>25.457408022227327 53.265308213233254</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6188</id>
+    <updated>2003-01-24T13:53:48.000Z</updated>
+    <title type="text">Observation:6188</title>
+    <georss:point>25.46274618782678 53.26557485919598</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6210</id>
+    <updated>2003-01-24T13:54:03.000Z</updated>
+    <title type="text">Observation:6210</title>
+    <georss:point>25.466265099961312 53.270117632151816</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6232</id>
+    <updated>2003-01-24T13:54:18.000Z</updated>
+    <title type="text">Observation:6232</title>
+    <georss:point>25.466001927855963 53.27598648551776</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6254</id>
+    <updated>2003-01-24T13:54:33.000Z</updated>
+    <title type="text">Observation:6254</title>
+    <georss:point>25.46128159085584 53.27866841565692</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6276</id>
+    <updated>2003-01-24T13:54:48.000Z</updated>
+    <title type="text">Observation:6276</title>
+    <georss:point>25.456824425961063 53.27548173550007</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6298</id>
+    <updated>2003-01-24T13:55:03.000Z</updated>
+    <title type="text">Observation:6298</title>
+    <georss:point>25.45708759806641 53.26961332972796</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6320</id>
+    <updated>2003-01-24T13:55:18.000Z</updated>
+    <title type="text">Observation:6320</title>
+    <georss:point>25.46180793506653 53.266931493062735</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6342</id>
+    <updated>2003-01-24T13:55:33.000Z</updated>
+    <title type="text">Observation:6342</title>
+    <georss:point>25.466622937145605 53.26973947831078</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6364</id>
+    <updated>2003-01-24T13:55:48.000Z</updated>
+    <title type="text">Observation:6364</title>
+    <georss:point>25.468607903119338 53.2751888252096</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6386</id>
+    <updated>2003-01-24T13:56:03.000Z</updated>
+    <title type="text">Observation:6386</title>
+    <georss:point>25.46533969220875 53.27981752442097</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6408</id>
+    <updated>2003-01-24T13:56:18.000Z</updated>
+    <title type="text">Observation:6408</title>
+    <georss:point>25.460086515324427 53.278996934858085</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6430</id>
+    <updated>2003-01-24T13:56:33.000Z</updated>
+    <title type="text">Observation:6430</title>
+    <georss:point>25.45810154935069 53.2735479738796</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6452</id>
+    <updated>2003-01-24T13:56:48.000Z</updated>
+    <title type="text">Observation:6452</title>
+    <georss:point>25.46136976026128 53.26891955310803</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6474</id>
+    <updated>2003-01-24T13:57:03.000Z</updated>
+    <title type="text">Observation:6474</title>
+    <georss:point>25.466677246284434 53.2696373437875</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6496</id>
+    <updated>2003-01-24T13:57:18.000Z</updated>
+    <title type="text">Observation:6496</title>
+    <georss:point>25.469985685549222 53.27439706212921</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6518</id>
+    <updated>2003-01-24T13:57:33.000Z</updated>
+    <title type="text">Observation:6518</title>
+    <georss:point>25.4695969457466 53.28025753160908</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6540</id>
+    <updated>2003-01-24T13:57:48.000Z</updated>
+    <title type="text">Observation:6540</title>
+    <georss:point>25.46482051943469 53.28281481156036</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6562</id>
+    <updated>2003-01-24T13:58:03.000Z</updated>
+    <title type="text">Observation:6562</title>
+    <georss:point>25.460432832925406 53.27951187364259</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6584</id>
+    <updated>2003-01-24T13:58:18.000Z</updated>
+    <title type="text">Observation:6584</title>
+    <georss:point>25.46082157272803 53.27365185053865</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6606</id>
+    <updated>2003-01-24T13:58:33.000Z</updated>
+    <title type="text">Observation:6606</title>
+    <georss:point>25.465597999066915 53.271094655177805</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6628</id>
+    <updated>2003-01-24T13:58:48.000Z</updated>
+    <title type="text">Observation:6628</title>
+    <georss:point>25.47040448800962 53.27395367841112</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6650</id>
+    <updated>2003-01-24T13:59:03.000Z</updated>
+    <title type="text">Observation:6650</title>
+    <georss:point>25.472446860183357 53.279377109584026</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6672</id>
+    <updated>2003-01-24T13:59:18.000Z</updated>
+    <title type="text">Observation:6672</title>
+    <georss:point>25.469227749481856 53.28404798091244</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6694</id>
+    <updated>2003-01-24T13:59:33.000Z</updated>
+    <title type="text">Observation:6694</title>
+    <georss:point>25.46396626660662 53.28329547412404</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6716</id>
+    <updated>2003-01-24T13:59:48.000Z</updated>
+    <title type="text">Observation:6716</title>
+    <georss:point>25.461923894432882 53.27787242526332</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6738</id>
+    <updated>2003-01-24T14:00:03.000Z</updated>
+    <title type="text">Observation:6738</title>
+    <georss:point>25.465143005134383 53.273201837511195</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6760</id>
+    <updated>2003-01-24T14:00:18.000Z</updated>
+    <title type="text">Observation:6760</title>
+    <georss:point>25.470461880150136 53.273841180924535</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6782</id>
+    <updated>2003-01-24T14:00:33.000Z</updated>
+    <title type="text">Observation:6782</title>
+    <georss:point>25.473887729018326 53.27850760293026</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6804</id>
+    <updated>2003-01-24T14:00:48.000Z</updated>
+    <title type="text">Observation:6804</title>
+    <georss:point>25.4736923289769 53.28438007746968</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6826</id>
+    <updated>2003-01-24T14:01:03.000Z</updated>
+    <title type="text">Observation:6826</title>
+    <georss:point>25.469003338936666 53.28712881458399</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6848</id>
+    <updated>2003-01-24T14:01:18.000Z</updated>
+    <title type="text">Observation:6848</title>
+    <georss:point>25.464509748937857 53.284005315623844</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6870</id>
+    <updated>2003-01-24T14:01:33.000Z</updated>
+    <title type="text">Observation:6870</title>
+    <georss:point>25.464705148979284 53.278133289356475</georss:point>
+  </entry>
+  <entry xmlns:georss="http://www.georss.org/georss/10">
+    <id>6892</id>
+    <updated>2003-01-24T14:01:48.000Z</updated>
+    <title type="text">Observation:6892</title>
+    <georss:point>25.469394139019517 53.27538465045843</georss:point>
+  </entry>
+</feed>
\ No newline at end of file

Added: addins/timedpointtrack/trunk/examples/xml/track1.xml
===================================================================
--- addins/timedpointtrack/trunk/examples/xml/track1.xml	                        (rev 0)
+++ addins/timedpointtrack/trunk/examples/xml/track1.xml	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,98 @@
+<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
+<channel>
+
+<title>Title for First trial track</title>
+<description>Description for first track</description>
+<category>Nelson</category>
+<item><pubDate>1995-12-12T05:00:00Z</pubDate><geo:lat>22.18628611</geo:lat><geo:long>20.30211944</geo:long><title>Phase Change</title><description>Start Phase A</description></item>
+<item><pubDate>1995-12-12T05:05:00Z</pubDate><geo:lat>22.18621944</geo:lat><geo:long>20.28514722</geo:long></item>
+<item><pubDate>1995-12-12T05:10:00Z</pubDate><geo:lat>22.18609722</geo:lat><geo:long>20.266425</geo:long></item>
+<item><pubDate>1995-12-12T05:15:00Z</pubDate><geo:lat>22.18279722</geo:lat><geo:long>20.24935</geo:long></item>
+<item><pubDate>1995-12-12T05:16:00Z</pubDate><geo:lat>22.18153889</geo:lat><geo:long>20.24605556</geo:long><title>Course Change</title><description>220 degs 4kts</description></item>
+<item><pubDate>1995-12-12T05:20:00Z</pubDate><geo:lat>22.1764</geo:lat><geo:long>20.23299444</geo:long></item>
+<item><pubDate>1995-12-12T05:25:00Z</pubDate><geo:lat>22.16996111</geo:lat><geo:long>20.21654167</geo:long></item>
+<item><pubDate>1995-12-12T05:30:00Z</pubDate><geo:lat>22.16351944</geo:lat><geo:long>20.20017222</geo:long></item>
+<item><pubDate>1995-12-12T05:35:00Z</pubDate><geo:lat>22.15710556</geo:lat><geo:long>20.18375278</geo:long></item>
+<item><pubDate>1995-12-12T05:40:00Z</pubDate><geo:lat>22.15062778</geo:lat><geo:long>20.16738889</geo:long></item>
+<item><pubDate>1995-12-12T05:42:00Z</pubDate><geo:lat>22.14803333</geo:lat><geo:long>20.16077222</geo:long><title>Comment</title><description>XO has bridge</description></item>
+<item><pubDate>1995-12-12T05:45:00Z</pubDate><geo:lat>22.14416389</geo:lat><geo:long>20.15091944</geo:long></item>
+<item><pubDate>1995-12-12T05:50:00Z</pubDate><geo:lat>22.13757778</geo:lat><geo:long>20.13483333</geo:long></item>
+<item><pubDate>1995-12-12T05:55:00Z</pubDate><geo:lat>22.12541667</geo:lat><geo:long>20.134125</geo:long></item>
+<item><pubDate>1995-12-12T06:00:00Z</pubDate><geo:lat>22.11250556</geo:lat><geo:long>20.13402778</geo:long></item>
+<item><pubDate>1995-12-12T06:05:00Z</pubDate><geo:lat>22.09960278</geo:lat><geo:long>20.13395</geo:long></item>
+<item><pubDate>1995-12-12T06:10:00Z</pubDate><geo:lat>22.08812222</geo:lat><geo:long>20.14054722</geo:long><title>Comment</title><description></description></item>
+<item><pubDate>1995-12-12T06:13:00Z</pubDate><geo:lat>22.08141389</geo:lat><geo:long>20.14618333</geo:long><title>Course Change</title><description>220 degs 4kts</description></item>
+<item><pubDate>1995-12-12T06:15:00Z</pubDate><geo:lat>22.07695278</geo:lat><geo:long>20.14992778</geo:long></item>
+<item><pubDate>1995-12-12T06:20:00Z</pubDate><geo:lat>22.06584167</geo:lat><geo:long>20.15931111</geo:long></item>
+<item><pubDate>1995-12-12T06:25:00Z</pubDate><geo:lat>22.05460278</geo:lat><geo:long>20.16871944</geo:long></item>
+<item><pubDate>1995-12-12T06:30:00Z</pubDate><geo:lat>22.04315833</geo:lat><geo:long>20.16791667</geo:long></item>
+<item><pubDate>1995-12-12T06:35:00Z</pubDate><geo:lat>22.03118611</geo:lat><geo:long>20.16143056</geo:long></item>
+<item><pubDate>1995-12-12T06:40:00Z</pubDate><geo:lat>22.01912222</geo:lat><geo:long>20.15486389</geo:long></item>
+<item><pubDate>1995-12-12T06:45:00Z</pubDate><geo:lat>22.00708333</geo:lat><geo:long>20.14833056</geo:long></item>
+<item><pubDate>1995-12-12T06:50:00Z</pubDate><geo:lat>21.99504444</geo:lat><geo:long>20.14181111</geo:long></item>
+<item><pubDate>1995-12-12T06:55:00Z</pubDate><geo:lat>21.98423889</geo:lat><geo:long>20.14733611</geo:long></item>
+<item><pubDate>1995-12-12T07:00:00Z</pubDate><geo:lat>21.97367222</geo:lat><geo:long>20.15803333</geo:long></item>
+<item><pubDate>1995-12-12T07:05:00Z</pubDate><geo:lat>21.96306111</geo:lat><geo:long>20.16874444</geo:long></item>
+<item><pubDate>1995-12-12T07:10:00Z</pubDate><geo:lat>21.95407222</geo:lat><geo:long>20.17233611</geo:long></item>
+<item><pubDate>1995-12-12T07:15:00Z</pubDate><geo:lat>21.95885556</geo:lat><geo:long>20.15766944</geo:long></item>
+<item><pubDate>1995-12-12T07:20:00Z</pubDate><geo:lat>21.96630833</geo:lat><geo:long>20.16956944</geo:long></item>
+<item><pubDate>1995-12-12T07:25:00Z</pubDate><geo:lat>21.97450556</geo:lat><geo:long>20.18388056</geo:long></item>
+<item><pubDate>1995-12-12T07:30:00Z</pubDate><geo:lat>21.98276389</geo:lat><geo:long>20.19838333</geo:long></item>
+<item><pubDate>1995-12-12T07:32:00Z</pubDate><geo:lat>21.98605278</geo:lat><geo:long>20.20413056</geo:long><title>Comment</title><description>Suspect opponent to North, slowing down</description></item>
+<item><pubDate>1995-12-12T07:33:00Z</pubDate><geo:lat>21.98691667</geo:lat><geo:long>20.20727778</geo:long><title>Comment</title><description>VIP visitors due. Helo retrieved.</description></item>
+<item><pubDate>1995-12-12T07:34:00Z</pubDate><geo:lat>21.98566944</geo:lat><geo:long>20.20985556</geo:long><title>Comment</title><description>Wind picked up. Switching off sensor Delta</description></item>
+<item><pubDate>1995-12-12T07:35:00Z</pubDate><geo:lat>21.9842</geo:lat><geo:long>20.21243611</geo:long><title>Comment</title><description>Heavenly dusk</description></item>
+<item><pubDate>1995-12-12T07:40:00Z</pubDate><geo:lat>21.97609444</geo:lat><geo:long>20.226425</geo:long></item>
+<item><pubDate>1995-12-12T07:45:00Z</pubDate><geo:lat>21.96786111</geo:lat><geo:long>20.240725</geo:long></item>
+<item><pubDate>1995-12-12T07:50:00Z</pubDate><geo:lat>21.9595</geo:lat><geo:long>20.25507778</geo:long></item>
+<item><pubDate>1995-12-12T07:55:00Z</pubDate><geo:lat>21.95118056</geo:lat><geo:long>20.26941389</geo:long></item>
+<item><pubDate>1995-12-12T08:00:00Z</pubDate><geo:lat>21.94862778</geo:lat><geo:long>20.28483056</geo:long></item>
+<item><pubDate>1995-12-12T08:05:00Z</pubDate><geo:lat>21.95295</geo:lat><geo:long>20.30239444</geo:long></item>
+<item><pubDate>1995-12-12T08:10:00Z</pubDate><geo:lat>21.957325</geo:lat><geo:long>20.32020278</geo:long></item>
+<item><pubDate>1995-12-12T08:15:00Z</pubDate><geo:lat>21.96172222</geo:lat><geo:long>20.33795278</geo:long></item>
+<item><pubDate>1995-12-12T08:20:00Z</pubDate><geo:lat>21.96616111</geo:lat><geo:long>20.35568611</geo:long></item>
+<item><pubDate>1995-12-12T08:25:00Z</pubDate><geo:lat>21.96355556</geo:lat><geo:long>20.371925</geo:long></item>
+<item><pubDate>1995-12-12T08:30:00Z</pubDate><geo:lat>21.95877778</geo:lat><geo:long>20.38858333</geo:long></item>
+<item><pubDate>1995-12-12T08:35:00Z</pubDate><geo:lat>21.95988889</geo:lat><geo:long>20.40708333</geo:long></item>
+<item><pubDate>1995-12-12T08:40:00Z</pubDate><geo:lat>21.96361944</geo:lat><geo:long>20.41884722</geo:long></item>
+<item><pubDate>1995-12-12T08:45:00Z</pubDate><geo:lat>21.96945556</geo:lat><geo:long>20.40425278</geo:long><title>Course Change</title><description>220 degs 4kts</description></item>
+<item><pubDate>1995-12-12T08:50:00Z</pubDate><geo:lat>21.9759</geo:lat><geo:long>20.38807778</geo:long></item>
+<item><pubDate>1995-12-12T08:55:00Z</pubDate><geo:lat>21.98237222</geo:lat><geo:long>20.37183889</geo:long></item>
+<item><pubDate>1995-12-12T09:00:00Z</pubDate><geo:lat>21.98880278</geo:lat><geo:long>20.35546667</geo:long></item>
+<item><pubDate>1995-12-12T09:05:00Z</pubDate><geo:lat>21.99968611</geo:lat><geo:long>20.34794722</geo:long></item>
+<item><pubDate>1995-12-12T09:10:00Z</pubDate><geo:lat>22.01179167</geo:lat><geo:long>20.34156389</geo:long></item>
+<item><pubDate>1995-12-12T09:15:00Z</pubDate><geo:lat>22.02168611</geo:lat><geo:long>20.34614444</geo:long></item>
+<item><pubDate>1995-12-12T09:20:00Z</pubDate><geo:lat>22.02811111</geo:lat><geo:long>20.36220833</geo:long></item>
+<item><pubDate>1995-12-12T09:25:00Z</pubDate><geo:lat>22.03456111</geo:lat><geo:long>20.37856389</geo:long><title>Phase Change</title><description>End Phase A</description></item>
+<item><pubDate>1995-12-12T09:30:00Z</pubDate><geo:lat>22.04145</geo:lat><geo:long>20.36952222</geo:long></item>
+<item><pubDate>1995-12-12T09:35:00Z</pubDate><geo:lat>22.04782222</geo:lat><geo:long>20.35348611</geo:long></item>
+<item><pubDate>1995-12-12T09:40:00Z</pubDate><geo:lat>22.05426389</geo:lat><geo:long>20.33713056</geo:long></item>
+<item><pubDate>1995-12-12T09:45:00Z</pubDate><geo:lat>22.06069444</geo:lat><geo:long>20.32085</geo:long></item>
+<item><pubDate>1995-12-12T09:46:00Z</pubDate><geo:lat>22.06198611</geo:lat><geo:long>20.31761111</geo:long><title>Phase Change</title><description>Start Phase B</description></item>
+<item><pubDate>1995-12-12T09:50:00Z</pubDate><geo:lat>22.06471944</geo:lat><geo:long>20.30389444</geo:long></item>
+<item><pubDate>1995-12-12T09:55:00Z</pubDate><geo:lat>22.07586667</geo:lat><geo:long>20.29758333</geo:long></item>
+<item><pubDate>1995-12-12T10:00:00Z</pubDate><geo:lat>22.08793889</geo:lat><geo:long>20.29113889</geo:long></item>
+<item><pubDate>1995-12-12T10:05:00Z</pubDate><geo:lat>22.10003333</geo:lat><geo:long>20.2848</geo:long></item>
+<item><pubDate>1995-12-12T10:10:00Z</pubDate><geo:lat>22.11219722</geo:lat><geo:long>20.27842222</geo:long></item>
+<item><pubDate>1995-12-12T10:15:00Z</pubDate><geo:lat>22.11530556</geo:lat><geo:long>20.26194167</geo:long></item>
+<item><pubDate>1995-12-12T10:20:00Z</pubDate><geo:lat>22.11756944</geo:lat><geo:long>20.24336667</geo:long></item>
+<item><pubDate>1995-12-12T10:25:00Z</pubDate><geo:lat>22.11986111</geo:lat><geo:long>20.22466944</geo:long></item>
+<item><pubDate>1995-12-12T10:30:00Z</pubDate><geo:lat>22.12238333</geo:lat><geo:long>20.20620833</geo:long></item>
+<item><pubDate>1995-12-12T10:35:00Z</pubDate><geo:lat>22.12890278</geo:lat><geo:long>20.216475</geo:long></item>
+<item><pubDate>1995-12-12T10:40:00Z</pubDate><geo:lat>22.12351944</geo:lat><geo:long>20.22643333</geo:long></item>
+<item><pubDate>1995-12-12T10:45:00Z</pubDate><geo:lat>22.12099722</geo:lat><geo:long>20.23426667</geo:long></item>
+<item><pubDate>1995-12-12T10:50:00Z</pubDate><geo:lat>22.12194167</geo:lat><geo:long>20.23018333</geo:long></item>
+<item><pubDate>1995-12-12T10:55:00Z</pubDate><geo:lat>22.11872778</geo:lat><geo:long>20.23548056</geo:long></item>
+<item><pubDate>1995-12-12T11:00:00Z</pubDate><geo:lat>22.11994167</geo:lat><geo:long>20.23541111</geo:long></item>
+<item><pubDate>1995-12-12T11:05:00Z</pubDate><geo:lat>22.11992778</geo:lat><geo:long>20.23948056</geo:long></item>
+<item><pubDate>1995-12-12T11:10:00Z</pubDate><geo:lat>22.11802222</geo:lat><geo:long>20.24473889</geo:long></item>
+<item><pubDate>1995-12-12T11:15:00Z</pubDate><geo:lat>22.11764444</geo:lat><geo:long>20.24835278</geo:long></item>
+<item><pubDate>1995-12-12T11:20:00Z</pubDate><geo:lat>22.12215556</geo:lat><geo:long>20.24788889</geo:long></item>
+<item><pubDate>1995-12-12T11:25:00Z</pubDate><geo:lat>22.11725278</geo:lat><geo:long>20.25047778</geo:long></item>
+<item><pubDate>1995-12-12T11:30:00Z</pubDate><geo:lat>22.12259722</geo:lat><geo:long>20.24290278</geo:long></item>
+<item><pubDate>1995-12-12T11:35:00Z</pubDate><geo:lat>22.12921944</geo:lat><geo:long>20.24653889</geo:long></item>
+<item><pubDate>1995-12-12T11:40:00Z</pubDate><geo:lat>22.13970833</geo:lat><geo:long>20.25221389</geo:long></item>
+<item><pubDate>1995-12-12T11:41:00Z</pubDate><geo:lat>22.14173889</geo:lat><geo:long>20.25330556</geo:long><title>Phase Change</title><description>End Phase B</description></item>
+</channel>
+</rss>
+

Added: addins/timedpointtrack/trunk/img/time-minus-mini.png
===================================================================
(Binary files differ)


Property changes on: addins/timedpointtrack/trunk/img/time-minus-mini.png
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: addins/timedpointtrack/trunk/img/time-plus-mini.png
===================================================================
(Binary files differ)


Property changes on: addins/timedpointtrack/trunk/img/time-plus-mini.png
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: addins/timedpointtrack/trunk/img/time-world-mini.png
===================================================================
(Binary files differ)


Property changes on: addins/timedpointtrack/trunk/img/time-world-mini.png
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: addins/timedpointtrack/trunk/img/timebar.png
===================================================================
(Binary files differ)


Property changes on: addins/timedpointtrack/trunk/img/timebar.png
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeDisplay.js
===================================================================
--- addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeDisplay.js	                        (rev 0)
+++ addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeDisplay.js	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,87 @@
+/**
+ * @requires: OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TimeDisplay
+ */
+OpenLayers.Control.TimeDisplay = OpenLayers.Class(OpenLayers.Control, {
+    
+    /** 
+     * Property: element
+     * {DOMElement} 
+     */
+    element: null,
+    
+    /**
+     * Constructor: OpenLayers.Control.TimeDisplay
+     * 
+     * Parameters:
+     * options - {DOMElement} Options for control.
+     */
+    initialize: function(options) {
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * Method: destroy
+     */
+    destroy: function() {
+         if (this.map) {
+             this.map.events.unregister('datechanged', this, this.redraw);
+         }
+         OpenLayers.Control.prototype.destroy.apply(this, arguments);
+     },
+
+    /**
+     * Method: draw
+     * {DOMElement}
+     */    
+    draw: function() {
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+
+        if (!this.element) {
+            this.div.left = "";
+            this.div.top = "";
+            this.div.className = this.displayClass;
+            this.element = this.div;
+        }
+        
+        this.redraw();
+        return this.div;
+    },
+   
+    /**
+     * Method: redraw  
+     */
+    redraw: function(evt) {
+
+        var newHtml = this.formatOutput(map.currentDateTime);
+
+        if (newHtml != this.element.innerHTML) {
+            this.element.innerHTML = newHtml;
+        }
+    },
+
+    /**
+     * Method: formatOutput
+     * Override to provide custom display output
+     *
+     * Parameters:
+     * mydate - {Date} Date/Time to display
+     */
+    formatOutput: function(mydate) {
+        if (!mydate) return "Unknown";
+        return mydate.toString();
+     },
+
+    /** 
+     * Method: setMap
+     */
+    setMap: function() {
+        OpenLayers.Control.prototype.setMap.apply(this, arguments);
+        this.map.events.register( 'datechanged', this, this.redraw);
+    },     
+
+    CLASS_NAME: "OpenLayers.Control.TimeDisplay"
+});
\ No newline at end of file

Added: addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSlider.js
===================================================================
--- addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSlider.js	                        (rev 0)
+++ addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSlider.js	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,155 @@
+/**
+ * @requires: OpenLayers/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TimeSlider
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TimeSlider = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * APIProperty: slideFactor
+     * {Integer} Number of pixels by which we'll slide the selected time in any direction
+     *     on clicking the arrow buttons.
+     */
+    slideFactor: 50,
+
+    /**
+     * Property: buttons
+     * {Array(DOMElement)} Array of Button Divs
+     */
+    buttons: null,
+
+    /**
+     * Property: position
+     * {<OpenLayers.Pixel>}
+     */
+    position: null,
+
+    /**
+     * Constructor: OpenLayers.Control.TimeSlider
+     *
+     * Parameters:
+     * options - {Object}
+     */
+    initialize: function(options) {
+        this.position = new OpenLayers.Pixel(OpenLayers.Control.TimeSlider.X,
+                                             OpenLayers.Control.TimeSlider.Y);
+        OpenLayers.Control.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+        OpenLayers.Control.prototype.destroy.apply(this, arguments);
+        while(this.buttons.length) {
+            var btn = this.buttons.shift();
+            btn.map = null;
+            OpenLayers.Event.stopObservingElement(btn);
+        }
+        this.buttons = null;
+        this.position = null;
+    },
+
+    /**
+     * Method: draw
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {DOMElement} A reference to the container div for the TimeSlider control.
+     */
+    draw: function(px) {
+        // initialize our internal div
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        px = this.position;
+
+        // place the controls
+        this.buttons = [];
+
+        var sz = new OpenLayers.Size(18,18);
+        var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
+
+        this._addButton("timein", "time-plus-mini.png",
+                        centered.add(0, sz.h*3+5), sz);
+        this._addButton("timeout", "time-minus-mini.png",
+                        centered.add(0, sz.h*5+5), sz);
+        return this.div;
+    },
+
+    /**
+     * Method: doubleClick
+     *
+     * Parameters:
+     * evt - {Event}
+     *
+     * Returns:
+     * {Boolean}
+     */
+    doubleClick: function (evt) {
+        OpenLayers.Event.stop(evt);
+        return false;
+    },
+
+    /**
+     * Method: buttonDown
+     *
+     * Parameters:
+     * evt - {Event}
+     */
+    buttonDown: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+
+        switch (this.btn.action) {
+            case "panup":
+                this.map.pan(0, -this.slideFactor);
+                break;
+            case "pandown":
+                this.map.pan(0, this.slideFactor);
+                break;
+            case "panleft":
+                this.map.pan(-this.slideFactor, 0);
+                break;
+            case "panright":
+                this.map.pan(this.slideFactor, 0);
+                break;
+            case "timein":
+                if (this.control.now < this.control.time.length) {
+                    this.control.now++;
+                    this.control.setMapTime();
+                    this.control.moveTimeBar();
+                }
+                break;
+            case "timeout":
+                if (this.control.now > 0) {
+                    this.control.now--;
+                    this.control.setMapTime();
+                    this.control.moveTimeBar();
+                }
+                break;
+        }
+
+        OpenLayers.Event.stop(evt);
+    },
+
+    CLASS_NAME: "OpenLayers.Control.TimeSlider"
+});
+
+/**
+ * Constant: X
+ * {Integer}
+ */
+OpenLayers.Control.TimeSlider.X = 4;
+
+/**
+ * Constant: Y
+ * {Integer}
+ */
+OpenLayers.Control.TimeSlider.Y = 80;

Added: addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSliderBar.js
===================================================================
--- addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSliderBar.js	                        (rev 0)
+++ addins/timedpointtrack/trunk/lib/OpenLayers/Control/TimeSliderBar.js	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,402 @@
+/**
+ * @requires OpenLayers/Control/TimeSlider.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TimeSliderBar
+ *
+ * Inherits from:
+ *  - <OpenLayers.Control.TimeSlider>
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TimeSliderBar = OpenLayers.Class(OpenLayers.Control.TimeSlider, {
+
+    /**
+     * APIProperty: timeStopWidth
+     */
+    timeStopWidth: 18,
+
+    /**
+     * APIProperty: timeStopHeight
+     */
+    timeStopHeight: 1,
+
+    /**
+     * Property: slider
+     */
+    slider: null,
+
+    /**
+     * Property: sliderEvents
+     * {<OpenLayers.Events>}
+     */
+    sliderEvents: null,
+
+    /**
+     * Property: timeBarDiv
+     * {DOMElement}
+     */
+    timeBarDiv: null,
+
+    /**
+     * Property: divEvents
+     * {<OpenLayers.Events>}
+     */
+    divEvents: null,
+
+    /**
+    * Ptoperty: time
+    * {Array}
+    */
+    time: new Array(),
+
+    /**
+    * Property: Continuous drag. If true, the control will set fire datechanged events while
+    *    being dragged.
+    * {bool}
+    */
+    continuous: false,
+
+    /**
+    * Property: The current Date of the Control
+    * {int}
+    */
+    now: 0,
+
+    /**
+     * Constructor: <OpenLayers.Control.PanZoomBar>
+     */
+    initialize: function() {
+        OpenLayers.Control.TimeSlider.prototype.initialize.apply(this, arguments);
+    },
+
+    /**
+     * APIMethod: destroy
+     */
+    destroy: function() {
+
+        this.div.removeChild(this.slider);
+        this.slider = null;
+
+        this.sliderEvents.destroy();
+        this.sliderEvents = null;
+
+        this.div.removeChild(this.timebarDiv);
+        this.timeBarDiv = null;
+
+        this.divEvents.destroy();
+        this.divEvents = null;
+
+        this.map.events.unregister("datechanged", this, this.updateBar);
+
+        OpenLayers.Control.TimeSlider.prototype.destroy.apply(this, arguments);
+    },
+
+    /**
+     * Method: setMap
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Control.TimeSlider.prototype.setMap.apply(this, arguments);
+    },
+
+    /**
+     * Method: redraw
+     * clear the div and start over.
+     */
+    redraw: function() {
+        if (this.div != null) {
+            this.div.innerHTML = "";
+        }
+        this.draw();
+    },
+
+    /**
+     * Method: draw
+     *
+     * Parameters:
+     * px - {<OpenLayers.Pixel>}
+     */
+    draw: function(px) {
+        // initialize our internal div
+        OpenLayers.Control.prototype.draw.apply(this, arguments);
+        px = this.position.clone();
+        //px.y+=150;
+
+        // place the controls
+        this.buttons = [];
+
+        var sz = new OpenLayers.Size(18,18);
+        var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
+        var wposition = sz.w;
+
+        this._addButton("timein", "time-plus-mini.png", centered.add(0, sz.h*3+5), sz);
+        centered = this._addTimeBar(centered.add(0, sz.h*4+5));
+        this._addButton("timeout", "time-minus-mini.png", centered, sz);
+        return this.div;
+    },
+
+    _addButton:function(id, img, xy, sz) {
+        var imgLocation = OpenLayers.TimedPointTrackImgPath + img;
+        var btn = OpenLayers.Util.createAlphaImageDiv(
+                                    "OpenLayers_Control_TimeSlider_" + id,
+                                    xy, sz, imgLocation, "absolute");
+
+        //we want to add the outer div
+        this.div.appendChild(btn);
+
+        OpenLayers.Event.observe(btn, "mousedown",
+            OpenLayers.Function.bindAsEventListener(this.buttonDown, {btn: btn, control: this}));
+        OpenLayers.Event.observe(btn, "dblclick",
+            OpenLayers.Function.bindAsEventListener(this.doubleClick, {btn: btn, control: this}));
+        OpenLayers.Event.observe(btn, "click",
+            OpenLayers.Function.bindAsEventListener(this.doubleClick, {btn: btn, control: this}));
+        btn.action = id;
+        btn.map = this.map;
+        btn.slideFactor = this.slideFactor;
+
+        //we want to remember/reference the outer div
+        this.buttons.push(btn);
+        return btn;
+    },
+
+    /**
+     * Method: _addTimeBar
+     *
+     * Parameters:
+     * location - {<OpenLayers.Pixel>} where timebar drawing is to start.
+     */
+    _addTimeBar:function(centered) {
+        //alert(lineLayer);
+        var imgLocation = OpenLayers.Util.getImagesLocation();
+
+        var id = "OpenLayers_Control_TimeSliderBar_Slider" + this.map.id;
+        var timesToEnd = this.time.length;
+        var slider = OpenLayers.Util.createAlphaImageDiv(id,
+                       centered.add(-1, timesToEnd * this.timeStopHeight),
+                       new OpenLayers.Size(20,9),
+                       imgLocation+"slider.png",
+                       "absolute");
+        this.slider = slider;
+
+        this.sliderEvents = new OpenLayers.Events(this, slider, null, true);
+        if (this.time.length) this.sliderEvents.register("mousedown", this, this.timeBarDown);
+        if (this.time.length) this.sliderEvents.register("mousemove", this, this.timeBarDrag);
+        if (this.time.length) this.sliderEvents.register("mouseup", this, this.timeBarUp);
+        if (this.time.length) this.sliderEvents.register("dblclick", this, this.doubleClick);
+        if (this.time.length) this.sliderEvents.register("click", this, this.doubleClick);
+
+        var sz = new OpenLayers.Size();
+        sz.h = this.timeStopHeight * this.time.length+10;
+        //alert(dumpObj(this.time, 'time', '-', 8));
+        sz.w = this.timeStopWidth;
+        var div = null;
+
+        if (OpenLayers.Util.alphaHack()) {
+            var id = "OpenLayers_Control_TimeSliderBar" + this.map.id;
+            div = OpenLayers.Util.createAlphaImageDiv(id, centered,
+                                      new OpenLayers.Size(sz.w,
+                                              this.timeStopHeight * this.time.length),
+                                      OpenLayers.TimedPointTrackImgPath + "timebar.png",
+                                      "absolute", null, "crop");
+            div.style.height = sz.h;
+        } else {
+            div = OpenLayers.Util.createDiv(
+                        'OpenLayers_Control_TimeSliderBar_Timebar' + this.map.id,
+                        centered,
+                        sz,
+                        OpenLayers.TimedPointTrackImgPath+"timebar.png");
+        }
+
+        this.timebarDiv = div;
+
+        this.divEvents = new OpenLayers.Events(this, div, null, true);
+        this.divEvents.register("mousedown", this, this.divClick);
+        this.divEvents.register("mousemove", this, this.passEventToSlider);
+        this.divEvents.register("dblclick", this, this.doubleClick);
+        this.divEvents.register("click", this, this.doubleClick);
+
+        this.div.appendChild(div);
+
+        this.startTop = parseInt(div.style.top);
+        this.div.appendChild(slider);
+
+        if (this.time.length) this.map.events.register("datechanged", this, this.updateBar);
+
+        centered = centered.add(0, this.timeStopHeight * this.time.length+10);
+        return centered;
+    },
+
+    /**
+     * Method: passEventToSlider
+     * This function is used to pass events that happen on the div, or the map,
+     * through to the slider, which then does its moving thing.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     */
+    passEventToSlider:function(evt) {
+        this.sliderEvents.handleBrowserEvent(evt);
+    },
+
+    /**
+     * Method: divClick
+     * Picks up on clicks directly on the timebar div
+     *           and sets the zoom level appropriately.
+     */
+    divClick: function (evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        var y = evt.clientY;
+        var top = OpenLayers.Util.pagePosition(evt.object)[1];
+        var levels = Math.floor((y - top)/this.timeStopHeight);
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: timeBarDown
+     * event listener for clicks on the slider
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     */
+    timeBarDown:function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        this.map.events.register("mousemove", this, this.passEventToSlider);
+        this.map.events.register("mouseup", this, this.passEventToSlider);
+        this.mouseDragStart = new OpenLayers.Pixel(evt.clientX, evt.clientY);
+        this.timeStart = this.mouseDragStart.clone();
+        this.div.style.cursor = "move";
+        // reset the div offsets just in case the div moved
+        this.timebarDiv.offsets = null;
+        OpenLayers.Event.stop(evt);
+    },
+
+    /**
+     * Method: timeBarDrag
+     * This is what happens when a click has occurred, and the client is
+     * dragging.  Here we must ensure that the slider doesn't go beyond the
+     * bottom/top of the timebar div, as well as moving the slider to its new
+     * visual location
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     */
+    timeBarDrag:function(evt) {
+        if (this.mouseDragStart != null) {
+            var deltaY = this.mouseDragStart.y - evt.clientY;
+            var offsets = OpenLayers.Util.pagePosition(this.timebarDiv);
+            if ((evt.clientY - offsets[1]) > 0 &&
+                (evt.clientY - offsets[1]) < parseInt(this.timebarDiv.style.height) - 2) {
+                var newTop = parseInt(this.slider.style.top) - deltaY;
+                this.slider.style.top = newTop+"px";
+                if (this.continuous) { 
+                    this.now += Math.round(deltaY/this.timeStopHeight);
+                    if (this.now < 0) this.now = 0;
+                    else if (this.now > this.time.length) this.now = this.time.length;
+                    this.setMapTime();
+                }
+            }
+            this.mouseDragStart = new OpenLayers.Pixel(evt.clientX, evt.clientY);
+            OpenLayers.Event.stop(evt);
+        }
+    },
+
+    /**
+     * Method: timeBarUp
+     * Perform cleanup when a mouseup event is received -- discover new time point
+     * switch to it.
+     *
+     * Parameters:
+     * evt - {<OpenLayers.Event>}
+     */
+    timeBarUp:function(evt) {
+        if (!OpenLayers.Event.isLeftClick(evt)) {
+            return;
+        }
+        if (this.timeStart) {
+            this.div.style.cursor="";
+            this.map.events.unregister("mouseup", this, this.passEventToSlider);
+            this.map.events.unregister("mousemove", this, this.passEventToSlider);
+            var deltaY = (this.timeStart.y+OpenLayers.Control.TimeSlider.Y-10) - (evt.clientY+OpenLayers.Control.TimeSlider.Y-10);
+            if (!this.continuous)
+                this.now += Math.round(deltaY/this.timeStopHeight);
+            if (this.now < 0) this.now = 0;
+            else if (this.now > this.time.length) this.now = this.time.length;
+            this.setMapTime();
+            //this.map.zoomTo(this.map.zoom + Math.round(deltaY/this.zoomStopHeight));
+            this.moveTimeBar();
+            this.mouseDragStart = null;
+            OpenLayers.Event.stop(evt);
+        }
+    },
+
+    /**
+     * Method: moveTimeBar
+     * Change the location of the slider to match the current zoom level.
+     */
+    moveTimeBar:function() {
+        var newTop = ((this.time.length - 1) - this.now) * this.timeStopHeight + this.startTop + 1;
+        this.slider.style.top = newTop + "px";
+    },
+
+    setTime: function(time) {
+        if (typeof(time) == 'object') {
+        alert(dumpObj(time, 'time', '-', 8));
+            this.time = time;
+            this.setMapTime();
+            this.redraw();
+        }
+    },
+
+    timein: function() {
+        if (this.now < this.time.length) {
+            this.now++;
+            this.setMapTime();
+        }
+    },
+
+    rangeFromTrack: function(geometry) {
+        var has = false;
+        var timecount = 0;
+        var component;
+        for (var i = 0, len=geometry.components.length; i < len; ++i) {
+            component = geometry.components[i];
+            has = false;
+            for (j=0; j < this.time.length; j++) {
+                if (OpenLayers.Date.equals(this.time[j],component.dateTime)) {
+                    has = true
+                    continue;
+                }
+            }
+            if (!has) this.time[timecount++] = component.dateTime;
+        }
+        this.redraw();
+    },
+
+    setMapTime: function() {
+        if (this.now < 0) this.now = 0;
+        else if (this.now >= this.time.length) this.now = this.time.length-1;
+        this.map.setTime(this.time[this.now]);
+    },
+
+    updateBar: function() {
+        var diff = Math.abs(this.time[0] - this.map.currentDateTime);
+        var best = 0;
+        for (var i=0; i < this.time.length; i++) {
+            if (diff > Math.abs(this.time[i] - this.map.currentDateTime)) {
+                diff = Math.abs(this.time[i] - this.map.currentDateTime);
+                best = i;
+            }
+        }
+        this.now = best;
+        this.moveTimeBar();
+    },
+
+    CLASS_NAME: "OpenLayers.Control.TimeSliderBar"
+});
\ No newline at end of file

Added: addins/timedpointtrack/trunk/lib/OpenLayers/Layer/TimedPointTrack.js
===================================================================
--- addins/timedpointtrack/trunk/lib/OpenLayers/Layer/TimedPointTrack.js	                        (rev 0)
+++ addins/timedpointtrack/trunk/lib/OpenLayers/Layer/TimedPointTrack.js	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,267 @@
+/**
+ * @requires OpenLayers/Layer/GML.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.TimedPointTrack
+ * Time-aware PointTrack layer to display ordered point features as a line, creating one
+ * LineString feature for each pair of two points and marking positions base on time.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.GML> 
+ */
+OpenLayers.Layer.TimedPointTrack = OpenLayers.Class(OpenLayers.Layer.GML, {
+  
+    /**
+     * APIProperty:
+     * interpolatePoints - {Boolean} If the flag is no, the layer 
+     *             will place the highlight over the data point nearest in 
+     *             time to the supplied value, over the later point if exactly
+     *             between two points. If the flag is yes, the layer will 
+     *             identify the data points either side of the time supplied,
+     *             and interpolate a position using their time values. The
+     *             default value is false;
+     */
+    interpolatePoints: false,
+    
+    /**
+     * APIProperty:
+     * permanentHighlight - {Boolean}  optional. If the time supplied by setTime
+     *             is outside the time period of the track, the permanentHighlight
+     *             value will be examined. If no, the highlight will not be shown.
+     *             If yes, the highlight will be placed at the start/end of the 
+     *             track as applicable. The default value is false;
+     */
+    permanentHighlight: false,
+    
+    /**
+     * APIProperty:
+     * highlightStyle - {OpenLayers.Style} optional. The style for the higlight, by
+     *             default this is that of the layer default PLUS
+     *
+     *           {pointRadius: 10, pointStyle: "square"}
+     *
+     *    note the extra pointStyle attribute, which define the appearance of the
+     *    highlight, available values are 'square' and 'circle' for now. 
+     *
+     */
+    highlightStyle: {},
+
+    /**
+     * APIProperty:
+     * highlight  - {<OpenLayers.Feature.Vector>} internal, used for drawing the
+     *             highlight feature
+     */
+    highlight: null,
+    
+    /**
+     * APIProperty:
+     * createFeatures - {Boolean} do we want features for items that have a title?
+     *     Default is true.
+     */
+    createFeatures: true,
+    
+    /**
+     * APIProperty: feedCategories
+     * {Object} Feed categories, keyed by schema. Each entry has term and
+     *     label properties.
+     */
+    feedCategories: {},
+    
+    /**
+     * Constructor: OpenLayers.TimedPointTrack
+     * Constructor for a new OpenLayers.TimedPointTrack instance.
+     *
+     * Parameters:
+     * name     - {String} name of the layer
+     * options  - {Object} Optional object with properties to tag onto the
+     *            instance.
+     */    
+    initialize: function(name, url, options) {
+        
+        var feedCategories = this.feedCategories;
+        
+        var defaultOptions = {
+            format: OpenLayers.Format.GeoRSS,
+            formatOptions: {
+                georssns: "http://www.georss.org/georss/10",
+                read: function(doc) {
+                    if(typeof doc == "string") { 
+                        doc = OpenLayers.Format.XML.prototype.read.apply(
+                            this, [doc]);
+                    }
+                    
+                    var feedCats = this.getElementsByTagNameNS(doc, '*', 'category');
+                    var cat;
+                    for(var i=0; i<feedCats.length; ++i) {
+                        cat = feedCats[i];
+                        if(cat.parentNode.nodeName == "feed") {
+                            feedCategories[cat.getAttribute("scheme")] = {
+                                term: cat.getAttribute("term"),
+                                label: cat.getAttribute("label")
+                            }
+                        }
+                    }
+            
+                    var itemlist = this.getElementsByTagNameNS(doc, '*', 'item');
+                    if(itemlist.length == 0) {
+                        itemlist = this.getElementsByTagNameNS(doc, '*', 'entry');
+                    }
+
+                    // create an empty linestring geometry for the track
+                    var pointtrack = new OpenLayers.Geometry.LineString();
+                    var len = itemlist.length;
+                    pointtrack.components = new Array(len);
+                    // Create the features array with an empty feature.
+                    // This feature will get the pointtrack geometry when
+                    // we are done with parsing the rss feed. Doing it
+                    // this way will ensure that the track is on bottom of
+                    // the markers.
+                    var features = [new OpenLayers.Feature.Vector()];
+                    var feature, component, pubDate, prevDate;
+                    for(var i=0; i<len; ++i) {
+                        feature = this.createFeatureFromItem(itemlist[i]);
+                        // add the point to the track
+                        component = feature.geometry;
+                        pubDate = OpenLayers.Date.smartParse(feature.attributes["pubDate"]);
+                        component.dateTime = pubDate;
+                        pointtrack.components[i] = component;
+
+
+                        if (i > 1 && feature.attributes["pubDate"]) {
+                            pointtrack.components[i-1].dateTime.duration = pubDate-prevDate;
+                        }
+                        prevDate = pubDate;
+
+                        // only add marker if it has something to say.
+                        if(options.createFeatures !== false && feature.attributes.title != "Untitled") {
+                            features.push(feature);
+                        }
+                    }
+                    
+                    features[0].geometry = pointtrack;
+                    features[0].attributes = {
+                        title: "The Track",
+                        description: "This track has been created by connecting the feed entries to a line."
+                    }
+                    return features;
+                }
+            }
+        };
+        
+        var localOptions = OpenLayers.Util.extend({}, options);
+        OpenLayers.Util.extend(defaultOptions.formatOptions,
+            options.formatOptions);
+        OpenLayers.Util.applyDefaults(localOptions, defaultOptions);
+        
+        OpenLayers.Layer.GML.prototype.initialize.apply(this,
+            [name, url, localOptions]);
+
+        OpenLayers.Util.applyDefaults(this.highlightStyle , OpenLayers.Feature.Vector.style["default"]);
+        OpenLayers.Util.extend(this.highlightStyle , {pointRadius: 5, graphicName: "square"} );
+        this.highlight = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(0,0),
+            {},
+            this.highlightStyle
+        );
+        this.events.register("datetimechanged", this, this.updateHighlight);
+
+        this.events.register("loadend", this, function() {
+            var line = this.features[0].geometry;
+            this.datetimeIntervals = [
+                line.components[0].dateTime,
+                line.components[line.components.length-1].dateTime
+            ];
+        })
+    },
+
+    /**
+     * APIMethod: updateHighlight
+     * Updates highlight location according to the layers' current time,
+     * usually called from function registered with the "datetimechanged" 
+     * event of the layer
+     *
+     */
+    updateHighlight: function(){
+        this.renderer.eraseFeatures([this.highlight]);
+        if (!this.currentDateTime || (!this.permanentHighlight && (this.getStartTime() > OpenLayers.Date.getEndDate(this.currentDateTime) || this.getFinishTime() < this.currentDateTime))) {
+            return;
+        }
+      
+        var minDist = Number.MAX_VALUE;
+        var points = this.features[0].geometry.components;
+        var len = points.length;
+        
+        var lo = 0;
+        var hi = points.length - 1;
+        
+        var cur, dist;
+        while(Math.abs(hi-lo) > 1) {
+            cur = parseInt((lo+hi)/2);
+            dist = this.currentDateTime - points[cur].dateTime;
+            if(Math.abs(dist) < minDist) {
+                minDist = Math.abs(dist);
+            }
+            if(dist > 0) {
+                lo = cur;
+            } else if(dist < 0) {
+                hi = cur;
+            } else {
+                hi = lo = cur;
+            }
+        }
+        
+        if(hi !== lo) {
+            var d1 = Math.abs(this.currentDateTime - points[lo].dateTime);
+            var d2 = Math.abs(this.currentDateTime - points[hi].dateTime);
+            cur = d1 < d2 ? lo : hi;
+        }
+        
+        var point = points[cur]
+        var time = point.dateTime;
+
+        if (this.interpolatePoints && point && time) {      // sanity check to see if we have all the required parameters for interpolation
+            var point1, point2;
+            var point1Index = cur;
+            if(time > this.currentDateTime) {
+                point1Index--;
+            }
+            point1Index = Math.min(len-2, point1Index);
+            point1Index = Math.max(0, point1Index);
+            point1 = points[point1Index];
+            point2 = points[point1Index+1];
+            if (point1Index == 0) {
+                // the first point has no duration, so take it from the 2nd.
+                point1.dateTime.duration = point2.dateTime.duration;
+            }
+            var pos = OpenLayers.Date.getPlaceInInterval(point1.dateTime, this.currentDateTime);
+            point = new OpenLayers.Geometry.Point(
+                 point1.x + (point2.x - point1.x) * pos,
+                 point1.y + (point2.y - point1.y) * pos
+            );
+        }
+
+        if (point) {
+            this.highlight.geometry = point.clone();
+            this.drawFeature(this.highlight);
+        }
+    },
+    
+    /**
+     * Method: setMap
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.GML.prototype.setMap.apply(this, arguments);
+        // make sure the highlights stays turned on and current with the map zoom
+        map.events.register("zoomend", this, this.updateHighlight);
+
+        // update the date of the layer from the map property and redraw to keeep up with changes
+        map.events.register("datechanged", this, this.setTimeFromMap);
+        map.events.register("datechanged", this, this.updateHighlight);
+    },
+        
+    CLASS_NAME: "OpenLayers.Layer.TimedPointTrack"
+});
\ No newline at end of file

Added: addins/timedpointtrack/trunk/lib/TimedPointTrack.js
===================================================================
--- addins/timedpointtrack/trunk/lib/TimedPointTrack.js	                        (rev 0)
+++ addins/timedpointtrack/trunk/lib/TimedPointTrack.js	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,366 @@
+/**
+ * @requires OpenLayers/Map.js
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Format/GeoRSS.js
+ */
+
+/**
+ * Addin: TimedPointTrack
+ */
+(function() {
+    var singleFile = (OpenLayers._scriptName == "OpenLayers.js");
+    var addinPath = OpenLayers._getScriptLocation() +
+        (singleFile ? "" : "addins/timedpointtrack/trunk/");
+    
+    if (!singleFile) {
+        var jsfiles = new Array(
+            "OpenLayers/Control/TimeDisplay.js",
+            "OpenLayers/Control/TimeSlider.js",
+            "OpenLayers/Control/TimeSliderBar.js",
+            "OpenLayers/Layer/TimedPointTrack.js",
+            "OpenLayers/Layer/TimedWMSTrack.js"
+        );
+
+        var agent = navigator.userAgent;
+        var docWrite = (agent.match("MSIE") || agent.match("Safari"));
+        if(docWrite) {
+            var allScriptTags = new Array(jsfiles.length);
+        }
+        var host = addinPath + "lib/";    
+        for (var i=0, len=jsfiles.length; i<len; i++) {
+            if (docWrite) {
+                allScriptTags[i] = "<script src='" + host + jsfiles[i] +
+                                   "'></script>"; 
+            } else {
+                var s = document.createElement("script");
+                s.src = host + jsfiles[i];
+                var h = document.getElementsByTagName("head").length ? 
+                           document.getElementsByTagName("head")[0] : 
+                           document.body;
+                h.appendChild(s);
+            }
+        }
+        if (docWrite) {
+            document.write(allScriptTags.join(""));
+        }
+    }
+
+    /**
+     * APIProperty: OpenLayers.TimedPointTrackImgPath
+     */
+    OpenLayers.TimedPointTrackImgPath = addinPath + "img/";
+    
+    /**
+     * Function: add
+     * Allows adding methods or properties to existing namespace hierarchies.
+     * 
+     * Parameters:
+     * ns  - {Object} Namespace that the new method or property belongs to
+     * name - {String} Name of the method or property
+     * obj  - {Object} The new method or property
+     */
+    var add = function(ns, name, obj) {
+        var c;
+        if(ns.prototype) {
+            ns.prototype[name] = obj;
+        } else if(ns) {
+            ns[name] = obj;
+        }
+        for (var o in ns) {
+            c = ns[o];
+            if (typeof c == "function") {
+                if (c.prototype) {
+                    c.prototype[name] = obj;
+                } else {
+                    c[name] = obj;
+                }
+            }
+       }
+    };
+    
+    OpenLayers.Map.prototype.EVENT_TYPES.push("datechanged");
+    
+    /**
+     * Property: OpenLayers.Map.currentDateTime
+     * {Date} The current date/time if the map has temporal layers
+     */
+    add(OpenLayers.Map, "currentDateTime", null);
+    
+    /**
+     * Method: OpenLayers.Map.setTime
+     * 
+     * Parameters:
+     * {Date} Sets the current date/time for the map and emits the datechanged signal
+     *
+     */
+    add(OpenLayers.Map, "setTime", function(dt) {
+        if (!this.currentDateTime || !OpenLayers.Date.equals(this.currentDateTime,dt)){
+            this.currentDateTime = dt;
+            this.events.triggerEvent("datechanged");
+        }
+    });
+    
+    
+    /**
+     * APIProperty: OpenLayers.Layer.datetimeIntervals
+     * {Array} A list of time Intervals which define the time periods in ascending
+     *     order.  If this is not set in the layer constructor, it will be set
+     *     based on other resolution related properties (maxExtent,
+     *     maxResolution, maxScale, etc.).
+     */
+    add(OpenLayers.Layer, "datetimeIntervals", null);
+    
+    
+    /**
+     * APIProperty: OpenLayers.Layer.currentDateTime
+     * {<OpenLayers.DateTime>} A moment or interval of time
+     */
+    add(OpenLayers.Layer, "currentDateTime", null);
+    
+    /**
+     * Method: OpenLayers.Layer.isTemporalLayer
+     * {Boolean} Whether or not the layer's features change through time.
+     *
+     */
+    add(OpenLayers.Layer, "isTemporalLayer", function () {
+        if (this.datetimeIntervals && this.datetimeIntervals.length > 0) {
+            return true;
+        }
+    });
+    
+    /**
+     * Method: OpenLayers.Layer.setTime
+     * {Date} Sets the current date/time in the layer
+     *
+     */
+    add(OpenLayers.Layer, "setTime", function (dt) {
+        if (!this.isTemporalLayer()) {
+            return;
+        }
+    
+        if (!this.currentDateTime || !OpenLayers.Date.equals(this.currentDateTime,dt)){
+            this.currentDateTime = dt;
+        }
+    });
+    
+    /**
+     * Method: OpenLayers.Layer.setTimeFromMap
+     * Sets the current date/time in the layer
+     */
+    add(OpenLayers.Layer, "setTimeFromMap", function () {
+        this.setTime(this.map.currentDateTime);
+    });
+    
+    /**
+     * Method: OpenLayers.Layer.getStartTime
+     * {Date} Returns the first date/time the layer is available for, null
+     *     if the layer has no temporal conotation
+     */
+    add(OpenLayers.Layer, "getStartTime", function () {
+        if (!this.isTemporalLayer()) {
+            return null;
+        }
+    
+        if (this.datetimeIntervals.length < 1) {
+            return null;
+        }
+    
+        return this.datetimeIntervals[0];
+    });
+    
+    /**
+     * Method: OpenLayers.Layer.getFinishTime
+     * {Date} Returns the last date/time the layer is available for, null
+     *     if the layer has no temporal conotation
+     *
+     */
+    add(OpenLayers.Layer, "getFinishTime", function () {
+        if (!this.isTemporalLayer()) {
+            return null;
+        }
+    
+        if (this.datetimeIntervals.length < 1) {
+            return null;
+        }
+    
+        return new Date(this.datetimeIntervals[this.datetimeIntervals.length -1].getTime() + this.datetimeIntervals[this.datetimeIntervals.length -1].duration);
+    });
+    
+    
+    /**
+     * Method: OpenLayers.Format.GeoRSS.createFeatureFromItem
+     * Return a feature from a GeoRSS Item.
+     *
+     * Parameters:
+     * item - {DOMElement} A GeoRSS item node.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>} A feature representing the item.
+     */
+    add(OpenLayers.Format.GeoRSS, "createFeatureFromItem", function(item) {
+        var geometry = this.createGeometryFromItem(item);
+     
+        /* Provide defaults for title and description */
+        var title = this.getChildValue(item, "*", "title", this.featureTitle);
+       
+        /* First try RSS descriptions, then Atom summaries */
+        var description = this.getChildValue(
+            item, "*", "description",
+            this.getChildValue(item, "*", "content", this.featureDescription)
+        );
+        
+        var pubDate = this.getChildValue(item, "*", "pubDate") ||
+            this.getChildValue(item, "*", "updated");
+    
+        /* If no link URL is found in the first child node, try the
+           href attribute */
+        var link = this.getChildValue(item, "*", "link");
+        if(!link) {
+            try {
+                link = this.getElementsByTagNameNS(item, "*", "link")[0].getAttribute("href");
+            } catch(e) {
+                link = null;
+            }
+        }
+    
+        var id = this.getChildValue(item, "*", "id", null);
+        
+        var data = {
+            "title": title,
+            "description": description,
+            "link": link,
+            "pubDate": pubDate
+        };
+        var feature = new OpenLayers.Feature.Vector(geometry, data);
+        feature.fid = id;
+        return feature;
+    });
+
+    /**
+     * APIMethod: OpenLayers.Date.contains
+     * Return whether the parameter date is fully contained within the interval of the Date method
+     * in whose context this function is called
+     *
+     * Parameters:
+     * {Date} source date context
+     * {Date} targetdate
+     *
+     * Returns:
+     * {bool}
+     */
+    add(OpenLayers.Date, "contains", function(source, targetdate) {
+        if (targetdate >= source && OpenLayers.Date.getEndDate(targetdate) <= OpenLayers.Date.getEndDate(source))
+            return true;
+        return false;
+    });
+
+    /**
+     * APIMethod: OpenLayers.Date.getEndDate
+     * Returns a {Date} object with the value of the end of the interval represented in this object
+     *
+     * Parameters:
+     * {Date} source date context
+     *
+     * Returns:
+     * {Date}
+     */
+    add(OpenLayers.Date, "getEndDate", function(source) {
+        return new Date(source.getTime() + source.duration);
+    });
+
+    /**
+     * APIMethod: OpenLayers.Date.merge
+     * Extends the start or duration of this Date object so it encompasses the interval targetdate object as well
+     * as the currect interval.
+     *
+     * Parameters:
+     * {Date} source date context
+     * {Date} targetdate
+     */
+    add(OpenLayers.Date, "merge", function(source, targetdate) {
+        var range = new Date(source);
+        if (targetdate < source) {
+            range.duration += source - targetdate;
+        range.setTime(targetdate.getTime());
+        }
+        var extend = OpenLayers.Date.getEndDate(targetdate) - OpenLayers.Date.getEndDate(source);
+        if ( extend > 0){
+            range.duration += extend;
+        }
+        return range;
+    });
+
+    /**
+     * APIMethod: OpenLayers.Date.getPlaceInInterval
+     * Returns a float value between 0 and 1 depending on where the targetdate parameter is in the
+     * date objects' time interval. If targetdate starts earlier than the date object, 0 is returned,
+     * if it starts after the end of the date object, 1 is returned.
+     *
+     * The optional second {bool} parameter defines whether the center of the
+     * targetdate's interval should be used (default is false).
+     *
+     * Parameters:
+     * {Date} source date context
+     * {Date} targetdate
+     * {bool} use center of targetdate if it's an interval
+     *
+     * Returns:
+     * {float} 0.0 - 1.0
+     */
+    add(OpenLayers.Date, "getPlaceInInterval", function(source, targetdate, center) {
+        if (!targetdate) return 0.0;
+        if (!source.duration) return 0.0;
+        var centerdate = new Date(targetdate);
+        if (center && targetdate.duration != 0)
+            centerdate.setTime(targetdate.getTime() + targetdate.duration/2);
+
+        if (centerdate > OpenLayers.Date.getEndDate(source))
+            return 1.0;
+        else if (source >= centerdate) // using <= to accomodate for non-interval datetimes
+            return 0.0;
+        else
+            return (centerdate - source) / source.duration ;
+    });
+
+    /**
+     * APIMethod: OpenLayers.Date.equals
+     * Returns whether the targetdate is equal by both start times and duration to the objects'
+     *
+     * Parameters:
+     * {Date} source date context
+     * {Date} targetdate
+     *
+     * Returns:
+     * {bool}
+     */
+    add(OpenLayers.Date, "equals", function(source, targetdate) {
+        if (source == null || targetdate == null) return false;
+        if (source.getTime() == targetdate.getTime() && source.duration == targetdate.duration) return true;
+        return false;
+    });
+
+
+    /**
+     * APIMethod: OpenLayers.Date.smartParse
+     * Parse String date regardless is it's RFC3339 or RFC822
+     *
+     * Parameters:
+     * {String} source date string
+     *
+     * Returns:
+     * {Date}
+     */
+    add(OpenLayers.Date, "smartParse", function(datestr) {
+        var targetdate = new Date();
+        targetdate.setTime(Date.parse(datestr));
+        if (datestr && !targetdate.getTime()) {
+            var pattern = /\D+/;
+            var datearray = datestr.split(pattern);
+            targetdate.setTime(Date.UTC(datearray[0], datearray[1]-1, datearray[2], datearray[3], datearray[4], datearray[5]));
+        }
+        return targetdate;
+    });
+
+    Date.prototype.duration = 0;
+
+})();

Added: addins/timedpointtrack/trunk/tests/BaseTypes.html
===================================================================
--- addins/timedpointtrack/trunk/tests/BaseTypes.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/BaseTypes.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,86 @@
+<html>
+<head>
+  <script src="../../../../lib/OpenLayers.js"></script>
+  <script src="../lib/TimedPointTrack.js"></script>
+  <script type="text/javascript">
+
+    function test_Date_contains(t) {
+        t.plan(5);
+        var base = new Date(Date.parse("Jul 8, 2005"));
+        var target = new Date(Date.parse("Jul 8, 2005"));
+        var contains = OpenLayers.Date.contains(base,target);
+        t.eq(contains, true, "equal dates are considered containing dates");
+
+        target = new Date(Date.parse("Jul 9, 2005"));
+        contains = OpenLayers.Date.contains(base,target);
+        t.eq(contains, false, "non-equal dates are not considered containing dates");
+
+        base.duration = 86400000;
+        contains = OpenLayers.Date.contains(base,target);
+        t.eq(contains, true, "A time interval contains it's endpoints");
+
+        target = new Date(Date.parse("Jul 8, 2005"));
+        target.duration = 86400000;
+        contains = OpenLayers.Date.contains(base,target);
+        t.eq(contains, true, "Two equal intervals are contained");
+
+        target.duration = 2*86400000;
+        contains = OpenLayers.Date.contains(base,target);
+        t.eq(contains, false, "Two  partially overlapping intervals are not contained");
+    }
+
+    function test_Date_equals(t) {
+        t.plan(3);
+        var base = new Date(Date.parse("Jul 8, 2005"));
+        var target = new Date(Date.parse("Jul 8, 2005"));
+        var equals = OpenLayers.Date.equals(base,target);
+        t.eq(equals, true, "Equal dates are... equal dates !");
+
+        base.duration = 86400000;
+        equals = OpenLayers.Date.equals(base,target);
+        t.eq(equals, false, "Durations have to be taken into account");
+
+        target.duration = 86400000;
+        equals = OpenLayers.Date.equals(base,target);
+        t.eq(equals, true, "Durations have to be taken into account");
+    }
+
+    function test_Date_merge(t) {
+        t.plan(3);
+        var base = new Date(Date.parse("Jul 8, 2005"));
+        var target = new Date(Date.parse("Jul 8, 2005"));
+        var merge = OpenLayers.Date.merge(base,target);
+        t.eq(OpenLayers.Date.equals(merge, base), true, "Merging with oneself is no change");
+
+        target.duration = 86400000;
+        merge = OpenLayers.Date.merge(base,target);
+        t.eq(OpenLayers.Date.equals(merge, target), true, "Duration has to be taken into account");
+
+        var base = new Date(Date.parse("Jul 7, 2005"));
+        merge = OpenLayers.Date.merge(base,target);
+        base.duration = 2*86400000;
+        t.eq(OpenLayers.Date.equals(merge, base), true, "Extend interval to fit");
+    } 
+
+    function test_Date_interval(t) {
+        t.plan(3);
+        var base = new Date(Date.parse("Jul 8, 2005"));
+        base.duration = 86400000;
+        var target = new Date(Date.parse("Jul 7, 2005"));
+        var value = OpenLayers.Date.getPlaceInInterval(base,target);
+        t.eq(value, 0, "Too early is 0");
+
+        target = new Date(Date.parse("Jul 10, 2005"));
+        value = OpenLayers.Date.getPlaceInInterval(base,target);
+        t.eq(value, 1, "Too late is 1");
+
+        target = new Date(Date.parse("Jul 8, 2005 12:00"));
+        value = OpenLayers.Date.getPlaceInInterval(base,target);
+        t.eq(value, 0.5, "Halfway is 0.5");
+    }        
+
+  </script>
+</head>
+<body>
+</body>
+</html>

Added: addins/timedpointtrack/trunk/tests/Control/TimeSlider.html
===================================================================
--- addins/timedpointtrack/trunk/tests/Control/TimeSlider.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/Control/TimeSlider.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,74 @@
+<html>
+<head>
+  <script src="../../../../../lib/OpenLayers.js"></script>
+  <script src="../../lib/TimedPointTrack.js"></script>
+  <script type="text/javascript">
+    var map; 
+    function test_Control_TimeSlider_constructor (t) {
+        t.plan( 4 );
+    
+        control = new OpenLayers.Control.PanZoom();
+        t.ok( control instanceof OpenLayers.Control.PanZoom, "new OpenLayers.Control.PanZoom returns object" );
+        t.eq( control.displayClass,  "olControlPanZoom", "displayClass is correct" );
+        control = new OpenLayers.Control.PanZoom({position: new OpenLayers.Pixel(100,100)});
+        t.eq( control.position.x, 100, "PanZoom X Set correctly."); 
+        t.eq( control.position.y, 100, "PanZoom y Set correctly."); 
+    }
+    function test_Control_TimeSlider_addControl (t) {
+        t.plan( 8 );
+        map = new OpenLayers.Map('map');
+        control = new OpenLayers.Control.PanZoom();
+        t.ok( control instanceof OpenLayers.Control.PanZoom, "new OpenLayers.Control.PanZoom returns object" );
+        t.ok( map instanceof OpenLayers.Map, "new OpenLayers.Map creates map" );
+        map.addControl(control);
+        t.ok( control.map === map, "Control.map is set to the map object" );
+        t.ok( map.controls[4] === control, "map.controls contains control" );
+        t.eq( parseInt(control.div.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Control div zIndexed properly" );
+        t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), map.Z_INDEX_BASE['Control'] + 5, "Viewport div contains control div" );
+        t.eq( control.div.style.top, "4px", "Control div top located correctly by default");
+
+        var control2 = new OpenLayers.Control.PanZoom();
+        map.addControl(control2, new OpenLayers.Pixel(100,100));
+        t.eq( control2.div.style.top, "100px", "2nd control div is located correctly");
+    }
+
+    function simulateClick(wnd, elem) {
+      var evt = wnd.document.createEvent("MouseEvents");
+      evt.initMouseEvent("mousedown", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+      elem.dispatchEvent(evt);
+
+      evt = wnd.document.createEvent("MouseEvents");
+      evt.initMouseEvent("mouseup", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+      elem.dispatchEvent(evt);
+
+      evt = wnd.document.createEvent("MouseEvents");
+      evt.initMouseEvent("click", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+      elem.dispatchEvent(evt);
+
+      evt = wnd.document.createEvent("MouseEvents");
+      evt.initMouseEvent("dblclick", true, true, wnd, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+      elem.dispatchEvent(evt);
+    }
+
+    function loader() {
+        control = new OpenLayers.Control.PanZoom();
+    
+        mapper = new OpenLayers.Map('map', { controls: [control]});
+        
+    
+        var layer = new OpenLayers.Layer.WMS("Test Layer", 
+            "http://octo.metacarta.com/cgi-bin/mapserv?",
+            {map: "/mapdata/vmap_wms.map", layers: "basic"});
+        mapper.addLayer(layer);
+    
+        centerLL = new OpenLayers.LonLat(0,0); 
+        mapper.setCenter(centerLL, 5);
+    }
+        
+
+  </script>
+</head>
+<body onload="loader()">
+    <div id="map" style="width: 1024px; height: 512px;"/>
+</body>
+</html>

Added: addins/timedpointtrack/trunk/tests/Control/TimeSliderBar.html
===================================================================
--- addins/timedpointtrack/trunk/tests/Control/TimeSliderBar.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/Control/TimeSliderBar.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,43 @@
+<html>
+<head>
+  <script src="../../../../../lib/OpenLayers.js"></script>
+  <script src="../../lib/TimedPointTrack.js"></script>
+  <script type="text/javascript">
+    var map; 
+    function test_Control_TimeSliderBar_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."); 
+    }
+    function test_Control_TimeSliderBar_addControl (t) {
+        t.plan( 8 );
+        map = new OpenLayers.Map('map', {controls:[]});
+        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();
+        t.ok( control instanceof OpenLayers.Control.PanZoomBar, "new OpenLayers.Control.PanZoomBar returns object" );
+        t.ok( map instanceof OpenLayers.Map, "new OpenLayers.Map creates map" );
+        map.addControl(control);
+        t.ok( control.map === map, "Control.map is set to the map object" );
+        t.ok( map.controls[0] === control, "map.controls contains control" );
+        t.eq( parseInt(control.div.style.zIndex), 1001, "Control div zIndexed properly" );
+        t.eq( parseInt(map.viewPortDiv.lastChild.style.zIndex), 1001, "Viewport div contains control div" );
+        t.eq( control.div.style.top, "4px", "Control div top located correctly by default");
+
+        var control2 = new OpenLayers.Control.PanZoomBar();
+        map.addControl(control2, new OpenLayers.Pixel(100,100));
+        t.eq( control2.div.style.top, "100px", "2nd control div is located correctly");
+    }
+
+  </script>
+</head>
+<body>
+    <div id="map" style="width: 1024px; height: 512px;"/>
+</body>
+</html>

Added: addins/timedpointtrack/trunk/tests/Layer.html
===================================================================
--- addins/timedpointtrack/trunk/tests/Layer.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/Layer.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,30 @@
+<html>
+<head>
+  <script src="../../../../lib/OpenLayers.js"></script>
+  <script src="../lib/TimedPointTrack.js"></script>
+  <script type="text/javascript">
+    var layer; 
+
+    function test_layer_temporal(t) {
+        t.plan(3);
+        var map = new OpenLayers.Map('map');
+        layer = new OpenLayers.Layer();
+        var d1 = new Date(Date.parse("Jul 8, 2005"));
+        var d2 = new Date(Date.parse("Jul 9, 2005"));
+        var d3 = new Date(Date.parse("Jul 10, 2005"));
+        map.addLayer(layer);
+        layer.datetimeIntervals = [ d1, d2, d3 ]; 
+        map.setTime(d2);
+        layer.setTimeFromMap();
+        t.eq(OpenLayers.Date.equals(layer.getStartTime(), d1), true, "First date");
+        t.eq(OpenLayers.Date.equals(layer.getFinishTime(), d3), true, "Last date");
+        t.eq(OpenLayers.Date.equals(layer.currentDateTime, d2), true, "Time on layer set");
+    }
+
+  </script>
+</head>
+<body>
+  <div id="map" style="width:500px;height:500px"></div>
+  <div id="map2" style="width:100px;height:100px"></div>
+</body>
+</html>

Added: addins/timedpointtrack/trunk/tests/Map.html
===================================================================
--- addins/timedpointtrack/trunk/tests/Map.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/Map.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,27 @@
+<html>
+<head>
+  <script src="../../../../lib/OpenLayers.js"></script>
+  <script src="../lib/TimedPointTrack.js"></script>
+  <script type="text/javascript">
+    var map;
+
+    function test_Map_setTime (t) {
+        t.plan( 2 );    
+        map = new OpenLayers.Map('map');
+        map.events.register("datechanged", {count: 0}, function() {
+            this.count++;
+            t.ok(true, "datechanged event was triggered");
+        });
+
+        var d= new Date(Date.parse("Jul 8, 2005"));
+        map.setTime(d);
+        t.eq(OpenLayers.Date.equals(map.currentDateTime, d), true, "Map date set");
+        map.setTime(new Date(Date.parse("Jul 8, 2005"))); // just to check that we don't get excessive events
+    }
+
+  </script>
+</head>
+<body>
+    <div id="map" style="width: 600px; height: 300px;"/>
+</body>
+</html>

Added: addins/timedpointtrack/trunk/tests/list-tests.html
===================================================================
--- addins/timedpointtrack/trunk/tests/list-tests.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/list-tests.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,7 @@
+<ul id="testlist">
+    <li>Control/TimeSlider.html</li>
+    <li>Control/TimeSliderBar.html</li>
+    <li>BaseTypes.html</li>
+    <li>Layer.html</li>
+    <li>Map.html</li>
+</ul>

Added: addins/timedpointtrack/trunk/tests/run-tests.html
===================================================================
--- addins/timedpointtrack/trunk/tests/run-tests.html	                        (rev 0)
+++ addins/timedpointtrack/trunk/tests/run-tests.html	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,2408 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html><head><title> Run the testsuite</title>
+<noscript>Javascript is disabled in your browser. This page cannot be displayed correctly without Javascript. Sorry. <br/> If you want to view this page, please change your browser settings so that Javascript is enabled.</noscript>
+<!--
+Test.AnotherWay version 0.5
+
+Copyright (c) 2005 Artem Khodush, http://straytree.org
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-->
+<style type="text/css">
+* { padding: 0; margin: 0; }
+html { height: 99%; }
+body { height: 98%; font: normal normal 10pt sans-serif }
+#col1 {  float: left; width: 27em; margin: 0 0 0 1em; overflow: visible; }
+#col2 {  position: relative; height: 98%; margin: 0 0.5em 0 28em; }
+#col1_header { margin-top: 0.5em; }
+#scroller { height: 400px; overflow: auto;}
+#testtable { margin: 0 0 2em 0; width: 97%; }
+#run_buttons { margin-bottom: 4em; }
+
+#right_header { padding-top: 0.8em; }
+#results_count { float: left; }
+.active_tab 			{ float: right; padding: 0 1em 0.2em 1em; background: #0af; border: 1px solid #048; border-bottom: none; cursor: pointer; cursor: hand;
+					 position: relative; top: -0.2em; }
+.inactive_tab 			{ float: right; padding: 0 1em 0 1em; background: #9bb; color: #444; border: 1px solid #9bb; border-bottom: none; cursor: pointer; cursor: hand; }
+.inactive_mouseover_tab 	{ float: right; padding: 0 1em 0 1em; background: #9bb; color: #062; border: 1px solid #062; border-bottom: none; cursor: pointer; cursor: hand; }
+
+#right_frame { overflow: auto; position: relative; top: -0.2em; clear: right; height: 95%; border: 1px solid #048; }
+
+#debug { display: none; }
+#debug p { margin: 2px 0 0 5em; text-indent: -4.8em; }
+
+#error { display: none; color: #c22; }
+
+#results p { margin: 0 0 2px 0; }
+/* cursor indicating that detailed results may be expanded/contracted */
+#results p.badtest { cursor: text; }
+#results p.ok, #results p.fail { cursor: pointer; cursor: hand; }
+
+/* colored squares in the results window at the left of test page names */
+#results p.ok .bullet { background: #6d6; }
+#results p.fail .bullet { background:  #d46; }
+#results p.badtest .bullet { background: #ea3; }
+#results p.loading .bullet { background: #48f; }
+#results p.running .bullet { background: #26e; }
+#results p.waiting .bullet { background: #04d; }
+/* highlight in the results line */
+#results p .warning { background: #ffc; }
+
+/* layout of the detailed results */
+.result_detail { padding-left: 3em; }
+.result_exception_detail { padding-left: 4em; }
+.result_exception_stack_detail { padding-left: 5em;  }
+.result_micro_detail { padding-left: 6em; }
+/* colouring in the detailed results */
+.result_detail .fail, .result_exception_detail .fail,  .result_micro_detail .fail { background: #ffd8d8; }
+
+/* "start recording" controls*/
+#record_div { margin-top: 3em; }
+#record_div p { margin-bottom: 0.5em; }
+#record_select { width: 88%; }
+#record_input { width: 53%; }
+</style>
+<script type="text/javascript">
+<!--
+if( typeof( Test )=="undefined" ) {
+	Test={};
+}
+Test.AnotherWay={};
+
+Test.AnotherWay._g_test_iframe=null; // frame where to load test pages
+Test.AnotherWay._g_test_frame_no_clear=false; // true - leave last page displayed after tests end
+Test.AnotherWay._g_test_page_urls=[]; // array of: { url: url, convention: "anotherway" or "jsan" }
+Test.AnotherWay._g_test_object_for_jsan=null; // test object for filling by tests that adhere to jsan Test.Simple calling convention
+Test.AnotherWay._g_pages_to_run=null; // list of pages to run automatically after loading
+Test.AnotherWay._g_run_on_main_load=false; // special handling for run_pages_to_run when it might be called before onload or before list of test pages is known.
+Test.AnotherWay._g_run_on_list_load=false;
+Test.AnotherWay._g_main_loaded=false;
+
+Test.AnotherWay._run_pages_to_run=function( called_from_outside )
+{
+	if( !Test.AnotherWay._g_main_loaded ) {
+		Test.AnotherWay._g_run_on_main_load=true;
+	}else {
+		var a_pages=Test.AnotherWay._g_pages_to_run;
+		if( a_pages=="all" ) {
+			for( var i=0; i<Test.AnotherWay._g_test_page_urls.length; ++i ) {
+				Test.AnotherWay._run_test_page( "test"+i );
+			}
+		}else if( a_pages!=null ) {
+			for( var run_i=0; run_i<a_pages.length; ++run_i ) {
+				var run_page=a_pages[run_i];
+				var found=false;
+				for( var all_i=0; all_i<Test.AnotherWay._g_test_page_urls.length; ++all_i ) {
+					if( run_page==Test.AnotherWay._g_test_page_urls[all_i].url ) {
+						Test.AnotherWay._run_test_page( "test"+all_i, called_from_outside );
+						found=true;
+						break;
+					}
+				}
+				if( !found ) {
+					Test.AnotherWay._show_error( "page specified to run is not found in the page list: "+run_page );
+					break;
+				}
+			}
+		}
+	}
+}
+
+Test.AnotherWay._add_test_page_url=function( test_url, convention )
+{
+	var table=document.getElementById( "testtable" );
+	var record_select=document.getElementById( "record_select" );
+	var index=Test.AnotherWay._g_test_page_urls.length;
+
+	// trim spaces.
+	if( test_url.match( "^(\\s*)(.*\\S)(\\s*)$" ) ) {
+		test_url=RegExp.$2;
+	}
+
+	Test.AnotherWay._g_test_page_urls[index]={ url: test_url, convention: convention };
+	var row=table.insertRow( -1 );
+
+	var cell;
+	var cell_child;
+	cell=row.insertCell( -1 );
+	cell_child=document.createElement( "input" );
+	cell_child.type="checkbox";
+	cell_child.id="checkbox"+index;
+    cell_child.checked='checked';
+    cell_child.defaultChecked='checked';
+	cell.appendChild( cell_child );
+
+	cell=row.insertCell( -1 );
+	cell.setAttribute( "width", "75%" );
+	cell.appendChild( document.createTextNode( test_url ) );
+
+	cell=row.insertCell( -1 );
+	cell_child=document.createElement( "input" );
+	cell_child.type="button";
+	cell_child.id="test"+index;
+	cell_child.value=" run ";
+	cell_child.onclick=Test.AnotherWay._run_one_onclick;
+	cell.appendChild( cell_child );
+
+	cell=row.insertCell( -1 );
+	cell.setAttribute( "width", "8em" );
+	cell_child=document.createElement( "span" );
+	cell.appendChild( cell_child );
+
+	var option=document.createElement( "option" );
+	option.appendChild( document.createTextNode( test_url ) );
+	record_select.appendChild( option );
+}
+Test.AnotherWay._show_error=function( msg )
+{
+	var error_div=document.getElementById( "error" );
+	error_div.innerHTML="";
+	error_div.appendChild( document.createTextNode( msg ) );
+	error_div.style.display="block";
+}
+
+// read urls from the list in the html file inside the list_iframe
+// fill on-screen list with urls and "run" buttons, and fill the g_test_page_urls object.
+Test.AnotherWay._list_iframe_onload=function()
+{
+	if( window.frames.list_iframe!=null && window.frames.list_iframe.location!="" && window.frames.list_iframe.location!="about:blank" ) {
+		var list_doc=window.frames.list_iframe.document;
+		var list=list_doc.getElementById( "testlist" );
+		if( list!=null ) {
+			for( var i=0; i<list.childNodes.length; ++i ) {
+				var item=list.childNodes[i];
+				if( item.nodeName=="LI" || item.nodeName=="li" ) {
+					var convention="anotherway";
+					if( Test.AnotherWay._get_css_class( item )=="jsan" ) {
+						convention="jsan";
+					}
+					Test.AnotherWay._add_test_page_url( item.innerHTML, convention );
+				}
+			}
+			if( Test.AnotherWay._g_run_on_list_load ) {
+				Test.AnotherWay._g_run_on_list_load=false;
+				Test.AnotherWay._run_pages_to_run();
+			}
+		}else {
+			Test.AnotherWay._show_error( "no list with id 'testlist' in a list file "+window.frames.list_iframe.location );
+		}
+	}
+}
+
+Test.AnotherWay._map_checkboxes=function( f )
+{
+	var table=document.getElementById( "testtable" );
+	var checks=table.getElementsByTagName( "INPUT" );
+	for( var i=0; i<checks.length; ++i ) {
+		if( checks[i].type=="checkbox" && checks[i].id.match( /^checkbox(\d+)$/ ) ) {
+			f( checks[i], RegExp.$1 );
+		}
+	}
+}
+Test.AnotherWay._run_all_onclick=function()
+{
+	Test.AnotherWay._map_checkboxes( function( c, id ) { Test.AnotherWay._run_test_page( "test"+id ); } );
+}
+Test.AnotherWay._run_selected_onclick=function()
+{
+	Test.AnotherWay._map_checkboxes( function( c, id ) { if( c.checked ) Test.AnotherWay._run_test_page( "test"+id ); } );
+}
+Test.AnotherWay._unselect_all_onclick=function()
+{
+	Test.AnotherWay._map_checkboxes( function( c, id ) { c.checked=false; } );
+}
+Test.AnotherWay._run_one_onclick=function()
+{
+	Test.AnotherWay._run_test_page( this.id );
+}
+
+// construct an object that will gather results of running one test function
+Test.AnotherWay._test_object_t=function( fun_name )
+{
+	this.name=fun_name; // name of the test function
+	this.n_plan=null; // planned number of assertions
+	this.n_ok=0; // # of ok assertions
+	this.n_fail=0; // # of failed assertions
+	this.exception=""; // if the function throwed an exception, it's its message
+	this.exception_stack=[]; // strings: function call stack from the exception
+	this.assertions=[]; // assertion results: array of { ok: 1 or 0, name: string }
+	this.wait_result_milliseconds=0; // how long to wait before collecting results from the test
+	this.second_wait_msg=null; // <p> status message (in addition to the page wait_msg)
+	this.delay_actions=[]; // array of actions to be perfomed after the test function returns
+				//	action : { acton_kind: "call" | "window" | "replay"
+				//				when "call": 		{ call_fn call_delay_milliseconds } call_fn takes nothing
+				//				when "window" : 	{ wnd_url wnd_wnd wnd_fn wnd_timeout_milliseconds wnd_dont_close } wnd_fn takes wnd
+				//				wnen "replay" : 	{ replay_wnd replay_events replay_event_i replay_checkpoints } checkpoint_fn takes this, wnd
+				//	}
+	this.delay_action_i=null; // index of delay action currently being performed
+	this.delay_prev_timer_time=0;	// for counting time while performing delay_actions
+	this.delay_current_milliseconds_left=0; // time left before the next action, runs down
+	this.delay_total_milliseconds_left=0; 	// for indication: total estimated time for all actions, runs up and down
+}
+
+Test.AnotherWay._test_object_t.prototype.ok=function( cond, name )
+{
+	if( cond ) {
+		++this.n_ok;
+		cond=1;
+	}else {
+		++this.n_fail;
+		cond=0;
+	}
+	this.assertions.push( { ok: cond, name: name } );
+}
+Test.AnotherWay._test_object_t.prototype.fail=function( name )
+{
+	this.ok( false, name );
+}
+Test.AnotherWay._test_object_t.prototype.plan=function( n )
+{
+	this.n_plan=n;
+}
+Test.AnotherWay._test_object_t.prototype.wait_result=function( seconds )
+{
+	this.wait_result_milliseconds=1000*seconds;
+}
+Test.AnotherWay._eq_fail_msg=function( path, what, expected, got )
+{
+	return "eq: "+path+" "+what+" differ: got "+got+", but expected "+expected;
+}
+Test.AnotherWay._array_eq=function( expected, got, path, msg )
+{
+	if( expected.length!=got.length ) {
+		msg.msg=Test.AnotherWay._eq_fail_msg( path, "array length", expected.length, got.length );
+		return false;
+	}
+	for( var i=0; i<expected.length; ++i ) {
+		if( !Test.AnotherWay._thing_eq( expected[i], got[i], path+"["+i+"]", msg ) ) {
+			return false;
+		}
+	}
+	return true;
+}
+Test.AnotherWay._object_eq=function( expected, got, path, msg )
+{
+	var v;
+	for( v in expected ) {
+		if( ! (v in got) ) {
+			msg.msg=Test.AnotherWay._eq_fail_msg( path+"."+v, "properties", expected[v], "undefined" );
+			return false;
+		}
+		if( !Test.AnotherWay._thing_eq( expected[v], got[v], path+"."+v, msg ) ) {
+			return false;
+		}
+	}
+	for( v in got ) {
+		if( ! (v in expected) ) {
+			msg.msg=Test.AnotherWay._eq_fail_msg( path+"."+v, "properties", "undefined", got[v] );
+			return false;
+		}
+	}
+	return true;
+}
+Test.AnotherWay._constructor_name=function( x )
+{
+	if( x==null ) {
+		return "";
+	}
+	var s="unknown";
+	try {
+		s=typeof( x.constructor );
+		if( s!="unknown" ) {
+			s=x.constructor.toString();
+		}
+	}catch( e ) {
+		s="unknown";
+	}
+	if( s=="unknown" ) {
+		// hackish attempt to guess a type
+		var is_array=true;
+		var index=0;
+		for( i in x ) {
+			if( i!=index ) {
+				is_array=false;
+			}
+			++index;
+		}
+		return is_array ? "Array" : "Object"; // for empty arrays/objects, this will be wrong half the time
+	}else if( s.match( /^\s*function\s+(\w+)\s*\(/ ) ) {
+		return RegExp.$1;
+	}else {
+	  var c = '';
+	  switch(typeof x) {
+	    case 'string':
+	      c = 'String';
+	      break;
+	    case 'object':
+	      c = 'Object';
+	      break;
+	    default:
+	      c = '';
+	  }
+		return c;
+	}
+}
+Test.AnotherWay._is_array=function( x )
+{
+	return Test.AnotherWay._constructor_name( x )=="Array";
+}
+Test.AnotherWay._is_value_type=function( x )
+{
+	cn=Test.AnotherWay._constructor_name( x );
+	return cn=="Number" || cn=="String" || cn=="Boolean" || cn=="Date";
+}
+Test.AnotherWay._thing_eq=function( expected, got, path, msg )
+{
+	if( expected==null && got==null ) {
+		return true;
+	}else if( (expected==null && got!=null) || (expected!=null && got==null) ) {
+		msg.msg=Test.AnotherWay._eq_fail_msg( path, "values", expected, got );
+		return false;
+	}else {
+		var expected_cn=Test.AnotherWay._constructor_name( expected );
+		var got_cn=Test.AnotherWay._constructor_name( got );
+		if( expected_cn!=got_cn ) {
+			msg.msg=Test.AnotherWay._eq_fail_msg( path, "types", expected_cn, got_cn );
+			return false;
+		}else {
+			if( Test.AnotherWay._is_array( expected ) ) {
+				return Test.AnotherWay._array_eq( expected, got, path, msg );
+			}else if( Test.AnotherWay._is_value_type( expected ) ) {
+				if( expected!=got ) {
+					msg.msg=Test.AnotherWay._eq_fail_msg( path, "values", expected, got );
+					return false;
+				}else {
+					return true;
+				}
+			}else { // just a plain object
+				return Test.AnotherWay._object_eq( expected, got, path, msg );
+			}
+		}
+	}
+}
+Test.AnotherWay._test_object_t.prototype.eq=function( got, expected, name )
+{
+	var msg={};
+	if( Test.AnotherWay._thing_eq( expected, got, "", msg ) ) {
+		this.ok( 1, name );
+	}else {
+		this.fail( name+". "+msg.msg );
+	}
+}
+Test.AnotherWay._test_object_t.prototype.like=function( got, expected, name )
+{
+	if( got.match( expected )!=null ) {
+		this.ok( 1, name );
+	}else {
+		this.fail( name+": got "+got+", but expected it to match: "+expected );
+	}
+}
+Test.AnotherWay._g_html_eq_span=null;
+Test.AnotherWay._html_eq_string_to_node=function( string_or_node, what, msg )
+{
+	if( string_or_node.nodeType!=null ) {
+		string_or_node=Test.AnotherWay._html_eq_node_to_string( string_or_node ); // double trip - to make properties assigned in scripts available as html node attributes
+	}
+	if( Test.AnotherWay._g_html_eq_span==null ) {
+		Test.AnotherWay._g_html_eq_span=document.createElement( "span" );
+	}
+	Test.AnotherWay._g_html_eq_span.innerHTML=string_or_node;
+	if( Test.AnotherWay._g_html_eq_span.childNodes.length!=1 ) {
+		msg.msg="bad "+what+" html string given (should contain exactly one outermost element): "+string_or_node;
+	}
+	return Test.AnotherWay._g_html_eq_span.childNodes[0].cloneNode( true );
+}
+Test.AnotherWay._html_eq_node_to_string=function( node ) {
+	if( Test.AnotherWay._g_html_eq_span==null ) {
+		Test.AnotherWay._g_html_eq_span=document.createElement( "span" );
+	}
+	Test.AnotherWay._g_html_eq_span.innerHTML="";
+	if( node.outerHTML!=null ) {
+		Test.AnotherWay._g_html_eq_span.innerHTML=node.outerHTML;
+	}else {
+            var clone = node.cloneNode(true);
+            var node = Test.AnotherWay._g_html_eq_span;
+            if(node.ownerDocument && node.ownerDocument.importNode) {
+                if(node.ownerDocument != clone.ownerDocument) {
+                    clone = node.ownerDocument.importNode(clone, true);
+                }
+            }
+            node.appendChild(clone);
+	}
+	return Test.AnotherWay._g_html_eq_span.innerHTML;
+}
+Test.AnotherWay._html_eq_path_msg=function( path )
+{
+	var msg="";
+	for( var i=0; i<path.length; ++i ) {
+		msg+=" [node "+path[i].node;
+		if( path[i].id!=null && path[i].id!="" ) {
+			msg+=" id "+path[i].id;
+		}else if( path[i].index!=null ) {
+			msg+=" at index "+path[i].index;
+		}
+		msg+="] "
+	}
+	return msg;
+}
+Test.AnotherWay._html_eq_fail_msg=function( path, what, expected, got )
+{
+	return Test.AnotherWay._html_eq_path_msg( path )+": "+what+" differ: got "+got+", but expected "+expected;
+}
+Test.AnotherWay._html_eq_remove_blank=function( text )
+{
+	if( text==null ) {
+		return "";
+	}else if( text.match( "^(\\s*)(.*\\S)(\\s*)$" ) ) {
+		return RegExp.$2;
+	}else if( text.match( "\s*" ) ) {
+		return "";
+	}
+	return text;
+}
+Test.AnotherWay._html_eq_remove_blank_nodes=function( node )
+{
+	var to_remove=[];
+	for( var child=node.firstChild; child!=null; child=child.nextSibling ) {
+		if( child.nodeType==3 ) {
+			var value=Test.AnotherWay._html_eq_remove_blank( child.nodeValue );
+			if( value=="" ) {
+				to_remove.push( child );
+			}else {
+				child.nodeValue=value;
+			}
+		}
+	}
+	for( var i=0; i<to_remove.length; ++i ) {
+		node.removeChild( to_remove[i] );
+	}
+}
+Test.AnotherWay._html_node_type_text=function( node_type )
+{
+	if( node_type==1 ) {
+		return "1 (html element)";
+	}else if( node_type==3 ) {
+		return "3 (text)";
+	}else {
+		return node_type;
+	}
+}
+Test.AnotherWay._html_eq_node=function( expected, got, path, msg, expected_loc_base, got_loc_base )
+{
+	if( expected.nodeType!=got.nodeType ) {
+		msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "node types", Test.AnotherWay._html_node_type_text( expected.nodeType ), Test.AnotherWay._html_node_type_text( got.nodeType ) );
+		return false;
+	}else if( expected.nodeType==3 ) {
+		if( expected.nodeValue!=got.nodeValue ) {
+			msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "text", expected.nodeValue, got.nodeValue );
+			return false;
+		}
+	}else if( expected.nodeType==1 ) {
+		if( expected.nodeName!=got.nodeName ) {
+			msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "node names", expected.nodeName, got.nodeName );
+			return false;
+		}
+		// compare attributes
+		var expected_attrs={};
+		var got_attrs={};
+		var i;
+		var a;
+		for( i=0; i<expected.attributes.length; ++i ) {
+			a=expected.attributes[i];
+			if( a.specified ) {
+				expected_attrs[a.name]=1;
+			}
+		}
+		for( i=0; i<got.attributes.length; ++i ) {
+			a=got.attributes[i];
+			if( a.specified ) {
+				got_attrs[a.name]=1;
+			}
+		}
+		for( a in expected_attrs ) {
+			if( ! (a in got_attrs) ) {
+				msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute sets differ: expected attribute "+a+" is missing";
+				return false;
+			}
+		}
+		for( a in got_attrs ) {
+			if( ! (a in expected_attrs) ) {
+				msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute sets differ: got extra attribute "+a;
+				return false;
+			}
+		}
+		for( a in expected_attrs ) {
+			var expected_value=expected.getAttribute( a );
+			var got_value=got.getAttribute( a );
+			if( typeof( expected_value )=="string" && typeof( got_value )=="string" ) {
+				expected_value=Test.AnotherWay._html_eq_remove_blank( expected_value );
+				got_value=Test.AnotherWay._html_eq_remove_blank( got_value );
+				var ok=expected_value==got_value;
+				if( !ok && (a=="href" || a=="HREF" )  ) { // try relative hrefs
+					var expected_relative_value=expected_value;
+					if( expected_loc_base!=null && expected_value.substring( 0, expected_loc_base.length )==expected_loc_base ) {
+						expected_relative_value=expected_value.substring( expected_loc_base.length );
+					}
+					var got_relative_value=got_value;
+					if( got_loc_base!=null && got_value.substring( 0, got_loc_base.length )==got_loc_base ) {
+						got_relative_value=got_value.substring( got_loc_base.length );
+					}
+					ok=expected_relative_value==got_relative_value;
+				}
+				if( !ok ) {
+					msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "attribute "+a+" values", expected_value, got_value );
+					return false;
+				}
+			}else if( typeof( expected_value )=="function" && typeof( got_value )=="function" ) {
+				expected_value=expected_value.toString();
+				got_value=got_value.toString();
+				if( expected_value!=got_value ) {
+					msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "attribute "+a+" values", expected_value, got_value );
+					return false;
+				}
+			}else {
+				var value_msg={};
+				if( !Test.AnotherWay._thing_eq( expected_value, got_value, "", value_msg ) ) {
+					msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute "+a+" values differ: "+value_msg.msg;
+					return false;
+				}
+			}
+		}
+		// compare child nodes
+		Test.AnotherWay._html_eq_remove_blank_nodes( expected );
+		Test.AnotherWay._html_eq_remove_blank_nodes( got );
+		var expected_length=expected.childNodes.length;
+		var got_length=got.childNodes.length;
+		if( expected_length<got_length ) {
+			msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": got "+(got_length-expected_length)+" extra child nodes";
+			return false;
+		}else if( expected_length>got_length ) {
+			msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": expected "+(expected_length-got_length)+" more child nodes";
+			return false;
+		}else {
+			for( i=0; i<expected_length; ++i ) {
+				var expected_node=expected.childNodes[i];
+				path.push( { node: expected_node.nodeName, id: expected_node.id, index: i } );
+				var eq=Test.AnotherWay._html_eq_node( expected_node, got.childNodes[i], path, msg, expected_loc_base, got_loc_base );
+				path.pop();
+				if( !eq ) {
+					return false;
+				}
+			}
+		}
+	}
+	return true;
+}
+Test.AnotherWay._html_eq_get_loc_base=function( node )
+{
+	var loc_base=document.location;
+	if( node.ownerDocument!=null ) {
+		loc_base=node.ownerDocument.location;
+	}
+	if( loc_base!=null ) {
+		loc_base=loc_base.href;
+		var slash_pos=loc_base.lastIndexOf( "/" );
+		if( slash_pos!=-1 ) {
+			loc_base=loc_base.substring( 0, slash_pos+1 );
+		}
+	}
+	return loc_base;
+}
+Test.AnotherWay._test_object_t.prototype.html_eq=function( got, expected, name )
+{
+	var msg={};
+	var expected_node=Test.AnotherWay._html_eq_string_to_node( expected, "expected", msg );
+	if( msg.msg!=null ) {
+		this.fail( name+" html_eq: "+msg.msg );
+	}else {
+		var got_node=Test.AnotherWay._html_eq_string_to_node( got, "got", msg );
+		if( msg.msg!=null ) {
+			this.fail( name+" html_eq: "+msg.msg );
+		}else {
+			var expected_loc_base=Test.AnotherWay._html_eq_get_loc_base( expected );
+			var got_loc_base=Test.AnotherWay._html_eq_get_loc_base( got );
+			if( Test.AnotherWay._html_eq_node( expected_node, got_node, [], msg, expected_loc_base, got_loc_base ) ) {
+				this.ok( 1, name );
+			}else {
+				var msg=name+" html_eq "+msg.msg;
+				var expected_str=Test.AnotherWay._html_eq_node_to_string( expected_node );
+				var got_str=Test.AnotherWay._html_eq_node_to_string( got_node );
+				msg+=".\n got html: "+got_str;
+				msg+=".\n expected html: "+expected_str;
+				this.fail( msg );
+			}
+		}
+	}
+}
+Test.AnotherWay._debug_pane_print=function( msg )
+{
+	var d=new Date();
+	var p=document.createElement( "p" );
+	p.appendChild( document.createTextNode( d.toLocaleTimeString()+" "+msg ) );
+	var debug_pane=document.getElementById( "debug" );
+	debug_pane.appendChild( p );
+	var debug_tab=document.getElementById( "debug_tab" );
+	var results_tab=document.getElementById( "results_tab" );
+	debug_tab.style.visibility="visible";
+	results_tab.style.visibility="visible";
+}
+Test.AnotherWay._test_object_t.prototype.debug_print=function( msg )
+{
+	Test.AnotherWay._debug_pane_print( this.name+": "+msg );
+}
+Test.AnotherWay._test_object_t.prototype.delay_call=function()
+{
+	var timeout_ms=200;
+	for( var i=0; i<arguments.length; ++i ) {
+		if( typeof( arguments[i] )!="function" ) {
+			timeout_ms=1000*arguments[i];
+		}else {
+			var action={ action_kind: "call", call_delay_milliseconds: timeout_ms, call_fn: arguments[i] };
+			this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action );
+			this.delay_actions.push( action );
+		}
+	}
+}
+Test.AnotherWay._test_object_t.prototype.open_window=function( url, fn, timeout_seconds )
+{
+	if( timeout_seconds==null ) {
+		timeout_seconds=4;
+	}
+	var no_close=document.getElementById( "dont_close_test_windows" );
+	var action={ action_kind: "window", wnd_url: url.toString(), wnd_wnd: null, wnd_fn: fn, wnd_timeout_milliseconds: timeout_seconds*1000, wnd_no_close: no_close.checked };
+	this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action );
+	this.delay_actions.push( action );
+}
+Test.AnotherWay._test_object_t.prototype.replay_events=function( wnd, events )
+{
+	if( Test.AnotherWay._g_no_record_msg!=null ) {
+		this.fail( "replay_events: "+Test.AnotherWay._g_no_record_msg );
+	}else {
+		var action={ action_kind: "replay", replay_wnd: wnd, replay_events: events.events, replay_event_i: null, replay_checkpoints: events.checkpoints };
+		this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action );
+		this.delay_actions.push( action );
+	}
+}
+Test.AnotherWay._action_estimate_milliseconds=function( action )
+{
+	var ms=0;
+	if( action.action_kind=="call" ) {
+		ms=action.call_delay_milliseconds;
+	}else if( action.action_kind=="window" ) {
+		ms=0;
+	}else if( action.action_kind=="replay" ) {
+		ms=0;
+		for( var i=0; i<action.replay_events.length; ++i ) {
+			ms+=action.replay_events[i]["time"]-0;
+		}
+	}
+	return ms;
+}
+
+Test.AnotherWay._g_timeout_granularity=200;
+Test.AnotherWay._g_tests_queue=[]; // vector of { url: string, test_objects : array of test_object_t, test_object_i: int, wait_msg: <p> object, loading_timeout_milliseconds: int, timeout_id: id }
+
+// load one html page, schedule further processing
+Test.AnotherWay._run_test_page=function( id, called_from_outside )
+{
+	if( id.match( /^test(\d+)/ ) ) {
+		id=RegExp.$1;
+		Test.AnotherWay._g_tests_queue.push( {
+			url: Test.AnotherWay._g_test_page_urls[id].url,
+			convention: Test.AnotherWay._g_test_page_urls[id].convention,
+			test_objects: []
+			} );
+		if( Test.AnotherWay._g_tests_queue.length==1 ) {
+			if( !called_from_outside ) {
+				// Crap. Be careful stepping around.
+				// For Mozilla and Opera, when this file is included into the frameset page that is in another directory (and _g_outside_path_correction!=null)
+				// but the test pages are started from within it (by "run" buttons), then:
+				// depending on whether the page is the first one loaded into the test frame or not,
+				// the base url for relative test pages differs.
+				// Crap, like I said.
+				Test.AnotherWay._g_tests_queue[0].suppress_outside_path_correction=true;
+			}
+			Test.AnotherWay._start_loading_page();
+		}
+	}
+}
+Test.AnotherWay._load_next_page=function()
+{
+	Test.AnotherWay._g_tests_queue.splice( 0, 1 );
+	if( Test.AnotherWay._g_tests_queue.length>0 ) {
+		Test.AnotherWay._start_loading_page();
+	}else {
+		if( !Test.AnotherWay._g_test_frame_no_clear ) {
+			Test.AnotherWay._g_test_iframe.location.replace( "about:blank" );
+		}
+	}
+}
+Test.AnotherWay._g_opera_path_correction=null; // ugly wart to support opera
+Test.AnotherWay._g_outside_path_correction=null; // ugly wart to accomodate Opera and Mozilla, where relative url relates to the directory where the page that calls this function is located
+Test.AnotherWay._set_iframe_location=function( iframe, loc, outside_path_correction )
+{
+	// allow to load only locations with the same origin
+	var proto_end=loc.indexOf( "://" );
+	if( proto_end!=-1 ) { // otherwise, it's safe to assume (for Opera, Mozilla and IE ) that loc will be treated as relative
+		var main_loc=window.location.href;
+		var host_end=loc.substring( proto_end+3 ).indexOf( "/" );
+		var ok=false;
+		if( host_end!=-1 ) {
+			var loc_origin=loc.substring( 0, proto_end+3+host_end+1 );
+			if( main_loc.length>=loc_origin.length && main_loc.substring( 0, loc_origin.length )==loc_origin ) {
+				ok=true;
+			}
+		}
+		if( !ok ) {
+			return { msg: "test pages may have only urls with the same origin as "+main_loc };
+		}
+	}
+	// opera cannot handle urls relative to file:// without assistance
+	if( window.opera!=null && window.location.protocol=="file:" && loc.indexOf( ":" )==-1 ) {
+		var base=window.location.href;
+		var q_pos=base.indexOf( "?" );
+		if( q_pos!=-1 ) {
+			base=base.substring( 0, q_pos );
+		}
+		var slash_pos=base.lastIndexOf( "/" );
+		if( slash_pos!=-1 ) {
+			base=base.substring( 0, slash_pos+1 );
+			Test.AnotherWay._g_opera_path_correction=base;
+			loc=base+loc;
+		}
+	}
+	// if this function is called from another page, and if that page is in another directory, correction is needed
+	if( outside_path_correction!=null ) {
+		var pos=loc.indexOf( outside_path_correction );
+		if( pos==0 ) {
+			loc=loc.substring( outside_path_correction.length+1 );
+		}
+	}
+	if( iframe.location!=null ) {
+		iframe.location.replace( loc );
+	}else {
+		iframe.src=loc;
+	}
+	return {};
+}
+Test.AnotherWay._start_loading_page=function()
+{
+	var test_page=Test.AnotherWay._g_tests_queue[0];
+	test_page.loading_timeout_milliseconds=12000;
+	test_page.timeout_id=setTimeout( Test.AnotherWay._loading_timeout, Test.AnotherWay._g_timeout_granularity );
+	test_page.wait_msg=Test.AnotherWay._print_counter_result( test_page.url, "loading...", test_page.loading_timeout_milliseconds, "loading" );
+	if( test_page.convention=="jsan" ) {
+		// the tests in that page will run when it's loading, so the test object must be ready
+		Test.AnotherWay._g_test_object_for_jsan=new Test.AnotherWay._test_object_t( test_page.url );
+	}
+	var outside_path_correction=null;
+	if( Test.AnotherWay._g_outside_path_correction!=null && !test_page.suppress_outside_path_correction ) {
+		outside_path_correction=Test.AnotherWay._g_outside_path_correction;
+	}
+	var result=Test.AnotherWay._set_iframe_location( Test.AnotherWay._g_test_iframe, test_page.url, outside_path_correction );
+	if( result.msg!=null ) {
+		Test.AnotherWay._unprint_result( test_page.wait_msg );
+		Test.AnotherWay._print_result( test_page.url, result.msg, "badtest", null );
+		Test.AnotherWay._load_next_page();
+	}
+}
+
+Test.AnotherWay._loading_timeout=function()
+{
+	var test_page=Test.AnotherWay._g_tests_queue[0];
+	test_page.loading_timeout_milliseconds-=Test.AnotherWay._g_timeout_granularity;
+	if( test_page.loading_timeout_milliseconds>0 ) {
+		Test.AnotherWay._update_msg_counter( test_page.wait_msg, (test_page.loading_timeout_milliseconds/1000).toFixed() );
+		test_page.timeout_id=setTimeout( Test.AnotherWay._loading_timeout, Test.AnotherWay._g_timeout_granularity );
+	}else {
+		Test.AnotherWay._unprint_result( test_page.wait_msg );
+		Test.AnotherWay._print_result( test_page.url, "Unable to load test page. Timeout expired", "badtest", null );
+		Test.AnotherWay._load_next_page();
+	}
+}
+
+Test.AnotherWay._strip_query_and_hash=function( s )
+{
+	var i=s.lastIndexOf( "#" );
+	if( i!=-1 ) {
+		s=s.substring( 0, i );
+	}
+	i=s.lastIndexOf( "?" );
+	if( i!=-1 ) {
+		s=s.substring( 0, i );
+	}
+	return s;
+}
+Test.AnotherWay._is_url_loaded=function( url, wnd )
+{
+	var loaded=false;
+	if( wnd!=null && wnd.location!=null ) {
+		// after some popup blocker interference, location may behave strange..
+		var location_s="";
+		location_s+=wnd.location;
+		if( location_s!="" ) {
+			var pathname=wnd.location.pathname;
+			var expected_url=url;
+			var i=expected_url.lastIndexOf( "#" );
+			if( i!=-1 ) {
+				expected_url=expected_url.substring( 0, i );
+			}
+			i=expected_url.lastIndexOf( "?" );
+			if( i!=-1 ) {
+				expected_url=expected_url.substring( 0, i );
+			}
+			i=expected_url.lastIndexOf( "/" );
+			if( i!=-1 && i!=expected_url.length-1 ) {
+				expected_url=expected_url.substring( i+1 );
+			}
+			i=pathname.indexOf( expected_url )
+			if( wnd.location.href==url || (i!=-1 && i==pathname.length-expected_url.length) ) {
+				if( /*window.opera==null*/wnd.document.readyState==null || wnd.document.readyState=="complete" ) { // for opera (and IE?), getElementById does not work until..
+					loaded=true;
+				}
+			}
+		}
+	}
+	return loaded;
+}
+// find and run all test functions in the g_cur_page html page.
+Test.AnotherWay._test_page_onload=function()
+{
+	if( Test.AnotherWay._g_tests_queue.length==0 ) {
+		return;
+	}
+	var test_page=Test.AnotherWay._g_tests_queue[0];
+	if( !Test.AnotherWay._is_url_loaded( test_page.url, Test.AnotherWay._g_test_iframe ) ) {
+		return;
+	}
+	clearTimeout( test_page.timeout_id );
+	Test.AnotherWay._unprint_result( test_page.wait_msg );
+
+	if( test_page.convention=="anotherway" ) {
+		// get test function names (those beginning with "test")
+		if( typeof( Test.AnotherWay._g_test_iframe.document.scripts )!='undefined' ) { // IE
+			for( var i=0; i<Test.AnotherWay._g_test_iframe.document.scripts.length; ++i ) {
+				var script_text=Test.AnotherWay._g_test_iframe.document.scripts[i].text;
+				var fun_sig="function test";
+				var fun_start=script_text.indexOf( fun_sig );
+
+				while( fun_start!=-1 ) {
+					script_text=script_text.substring( fun_start, script_text.length );
+					var fun_end=script_text.indexOf( '(' );
+					var fun_name=script_text.substring( "function ".length,  fun_end );
+                                        var whitespace = fun_name.indexOf( ' ' );
+                                        if (whitespace >= 0)
+                                            fun_name = fun_name.substring( 0, whitespace );
+					test_page.test_objects.push( new Test.AnotherWay._test_object_t( fun_name ) );
+					script_text=script_text.substring( fun_end, script_text.length );
+					fun_start=script_text.indexOf( fun_sig  );
+				}
+			}
+		}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; }
+                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 ) );
+					}
+				}
+			}
+		}
+	}else if( test_page.convention=="jsan" ) {
+		// the test object is already filled with results
+		test_page.test_objects.push( Test.AnotherWay._g_test_object_for_jsan );
+	}
+
+	if( test_page.test_objects.length==0 ) {
+		Test.AnotherWay._print_result( test_page.url,  "No test functions defined in the page", "badtest", null );
+		Test.AnotherWay._load_next_page();
+		return;
+	}
+
+	test_page.wait_msg=Test.AnotherWay._print_result( test_page.url, "running tests..<span class=\"counter\">"+test_page.test_objects.length+"</span>", "running", null );
+
+	test_page.test_object_i=0;
+	Test.AnotherWay._run_more_tests();
+}
+
+Test.AnotherWay._handle_exception=function( o, e, title )
+{
+	var s=title+": "+typeof( e )+": ";
+	if( e.message!=null ) {
+		s+=e.message;
+	}else if( e.description!=null ) {
+		s+=e.description;
+	}else {
+		s+=e.toString();
+	}
+//	if( e.location!=null ) {  // XXX figure out how to display exception location if it's present (like in mozilla)
+//		s+=" location: "+e.location.toString();
+//	}
+	o.exception=s;
+	s=[];
+	if( e.stack ) {
+		var lines=e.stack.split( "\n" );
+		for( var i=0; i<lines.length; ++i ) {
+			// format of the line: func_name(args)@file_name:line_no
+			if( lines[i].match( /(\w*)\(([^\)]*)\)@(.*):([^:]*)$/ ) ) {
+				var func_name=RegExp.$1;
+				if( func_name.length==0 ) {
+					func_name="<anonymous>";
+				}
+				s.push( "in "+func_name+"( "+RegExp.$2+") at "+RegExp.$3+" line "+RegExp.$4+"\n" );
+			}
+		}
+	}
+	o.exception_stack=s;
+}
+
+Test.AnotherWay._run_more_tests=function()
+{
+	var test_page=Test.AnotherWay._g_tests_queue[0];
+	while( test_page.test_object_i<test_page.test_objects.length ) {
+		Test.AnotherWay._update_msg_counter( test_page.wait_msg, (1+test_page.test_object_i)+"/"+test_page.test_objects.length );
+		var o=test_page.test_objects[test_page.test_object_i];
+		if( test_page.convention=="anotherway" ) {
+			try {
+				Test.AnotherWay._g_test_iframe[o.name]( o );
+			}catch( e ) {
+				Test.AnotherWay._handle_exception( o, e, "" );
+			}
+		} // for "jsan" convention, test has run already
+		if( o.delay_actions.length>0 || o.wait_result_milliseconds>0 ) {
+			o.delay_total_milliseconds_left+=o.wait_result_milliseconds;
+			Test.AnotherWay._delay_actions_timeout();
+			return;
+		}
+		++test_page.test_object_i;
+	}
+	Test.AnotherWay._unprint_result( test_page.wait_msg );
+	Test.AnotherWay._print_result( test_page.url, null, null, test_page.test_objects );
+	Test.AnotherWay._load_next_page();
+}
+
+Test.AnotherWay._delay_actions_timeout=function()
+{
+	var test_page=Test.AnotherWay._g_tests_queue[0];
+	var test_object=test_page.test_objects[test_page.test_object_i];
+	var finished=true;
+	if( test_object.delay_action_i==null ) {
+		// set up to start first action
+		test_object.delay_action_i=-1;
+	}else {
+		// perform current action
+		var milliseconds_passed=(new Date()).getTime()-test_object.delay_prev_timer_time;
+		test_object.delay_current_milliseconds_left-=milliseconds_passed;
+		test_object.delay_total_milliseconds_left-=milliseconds_passed;
+		finished=Test.AnotherWay._delay_continue_action( test_object, milliseconds_passed );
+	}
+	while( finished && test_object.delay_action_i<test_object.delay_actions.length ) {
+		++test_object.delay_action_i; // start next action
+		finished=Test.AnotherWay._delay_start_action( test_object );
+	}
+	if( test_object.delay_action_i<=test_object.delay_actions.length ) { // any more actions left ?
+		test_object.delay_prev_timer_time=(new Date()).getTime();
+		var next_timeout=Test.AnotherWay._g_timeout_granularity;
+		if( test_object.delay_current_milliseconds_left<next_timeout ) {
+			next_timeout=test_object.delay_current_milliseconds_left;
+		}
+		if( test_object.second_wait_msg!=null ) {
+			Test.AnotherWay._update_msg_counter( test_object.second_wait_msg, (test_object.delay_total_milliseconds_left/1000).toFixed() );
+		}
+		setTimeout( Test.AnotherWay._delay_actions_timeout, next_timeout );
+	}else { // no more actions left. run the next test.
+		if( test_object.second_wait_msg!=null ) {
+			Test.AnotherWay._unprint_result( test_object.second_wait_msg );
+			test_object.second_wait_msg=null;
+		}
+		++test_page.test_object_i;
+		Test.AnotherWay._run_more_tests();
+	}
+}
+Test.AnotherWay._delay_start_action=function( test_object )
+{
+	var finished=false;
+	var wait_msg="";
+	if( test_object.delay_action_i==test_object.delay_actions.length ) {
+		if( test_object.wait_result_milliseconds>0 ) {
+			test_object.delay_current_milliseconds_left=test_object.wait_result_milliseconds; // wait for result
+			wait_msg="waiting for results..";
+		}else {
+			++test_object.delay_action_i; // dont wait for result
+		}
+	}else {
+		var action=test_object.delay_actions[test_object.delay_action_i];
+		if( action.action_kind=="call" ) {
+			test_object.delay_current_milliseconds_left=action.call_delay_milliseconds;
+			wait_msg="performing delayed calls..";
+		}else if( action.action_kind=="window" ) {
+			if( Test.AnotherWay._g_opera_path_correction!=null && action.wnd_url.indexOf( ":" )==-1 ) {
+				action.wnd_url=Test.AnotherWay._g_opera_path_correction+action.wnd_url;
+			}
+			action.wnd_wnd=window.open( action.wnd_url, "_blank" );
+			if( action.wnd_wnd==null ) {
+				finished=true;
+				test_object.fail( "unable to open window for "+action.wnd_url );
+			}else {
+				test_object.delay_current_milliseconds_left=action.wnd_timeout_milliseconds;
+				wait_msg="opening window..";
+			}
+		}else if( action.action_kind=="replay" ) {
+			if( action.replay_events.length==0 ) {
+				finished=true;
+			}else {
+				action.replay_event_i=0;
+				test_object.delay_current_milliseconds_left=action.replay_events[0]["time"];
+				wait_msg="replaying events..";
+			}
+		}
+	}
+	if( test_object.second_wait_msg!=null ) {
+		Test.AnotherWay._unprint_result( test_object.second_wait_msg );
+	}
+	if( wait_msg!="" ) {
+		var test_page=Test.AnotherWay._g_tests_queue[0];
+		test_object.second_wait_msg=Test.AnotherWay._print_counter_result( test_page.url, wait_msg, test_object.delay_total_milliseconds_left, "waiting" );
+	}else {
+		test_object.second_wait_msg=null;
+	}
+	return finished;
+}
+Test.AnotherWay._delay_continue_action=function( test_object, milliseconds_passed )
+{
+	var finished=test_object.delay_current_milliseconds_left<=0;
+	if( test_object.delay_action_i==test_object.delay_actions.length ) { // action is "waiting for results"
+		if( test_object.n_plan!=null && test_object.n_plan==test_object.n_ok+test_object.n_fail ) {
+			finished=true; // if all assertions results are recorded, don't wait any more
+		}
+		if( finished ) {
+			++test_object.delay_action_i; // move on to the next test
+		}
+	}else {
+		var action=test_object.delay_actions[test_object.delay_action_i];
+		if( action.action_kind=="call" ) {
+			if( finished ) {
+				try {
+					action.call_fn();
+				}catch( e ) {
+					Test.AnotherWay._handle_exception( test_object, e, "in delay_call" );
+				}
+			}
+		}else if( action.action_kind=="window" ) {
+			test_object.delay_total_milliseconds_left+=milliseconds_passed; // for "window", the countdown is suspended since it's unknown how long it will take
+			if( Test.AnotherWay._is_url_loaded( action.wnd_url, action.wnd_wnd ) ) {
+				try {
+					action.wnd_fn( action.wnd_wnd );
+				}catch( e ) {
+					Test.AnotherWay._handle_exception( test_object, e, "in open_window function call" );
+				}
+				finished=true;
+			}else if( finished ) {
+				test_object.fail(  "unable to open window for url '"+action.wnd_url+"'. timeout expired" );
+			}
+		}else if( action.action_kind=="replay" ) {
+			if( finished ) {
+//				try {
+					Test.AnotherWay._delay_replay_event( test_object, action.replay_wnd, action.replay_events[action.replay_event_i], action.replay_checkpoints );
+//				}catch( e ) { // disabled, until I know how to gel location info from an exception
+//					Test.AnotherWay._handle_exception( test_object, e, "while replaying event" );
+//				}
+				++action.replay_event_i;
+				finished=action.replay_event_i==action.replay_events.length;
+				if( !finished ) {
+					test_object.delay_current_milliseconds_left=action.replay_events[action.replay_event_i]["time"];
+				}
+			}
+		}
+	}
+	return finished;
+}
+Test.AnotherWay._delay_replay_event=function( test_object, wnd, event, checkpoints )
+{
+	if( event.type=="_checkpoint" ) {
+		var checkpoint_n=event.which;
+		var prev_n_fail=test_object.n_fail;
+		checkpoints[checkpoint_n]( test_object, wnd );
+		var flash_color= prev_n_fail==test_object.n_fail ? "#2f2" : "#f22" ;
+		Test.AnotherWay._record_flash_border( flash_color );
+	}else if( event.type=="click" || event.type=="mouseover" || event.type=="mouseout" || event.type=="mousemove" || event.type=="mousedown" || event.type=="mouseup" ) {
+		var target=Test.AnotherWay._record_node_path_to_node( event["target"], wnd.document );
+		if( target!=null ) {
+			Test.AnotherWay._record_control_update_highlight( target, "ball", event );
+			var e=wnd.document.createEvent( "MouseEvents" );
+			var related_target=Test.AnotherWay._record_node_path_to_node( event["relatedTarget"], wnd.document );
+			e.initMouseEvent(
+				event["type"],
+				event["cancelable"],
+				event["bubbles"],
+				wnd.document.defaultView,
+				event["detail"],
+				event["screenX"],
+				event["screenY"],
+				event["clientX"],
+				event["clientY"],
+				event["ctrlKey"],
+				event["altKey"],
+				event["shiftKey"],
+				event["metaKey"],
+				event["button"],
+				Test.AnotherWay._record_node_path_to_node( event["relatedTarget"], wnd.document )
+			);
+			// Firefox 1.0.6 somehow loses relatedTarget somewhere on the way. Pass through our own, for those who choose to care.
+			e.passThroughRelatedTarget=related_target;
+			target.dispatchEvent( e );
+		}
+	}else if( event.type=="keyup" || event.type=="keydown" || event.type=="keypress" ) {
+		var e=wnd.document.createEvent( "KeyboardEvents" ); // forget it. Apparently it's not supported neither by mozilla nor by opera.
+		e.initKeyboardEvent(
+				event["type"],
+				event["cancelable"],
+				event["bubbles"],
+				wnd.document.defaultView,
+				event["which"],
+				event["which"],
+				event["ctrlKey"],
+				event["altKey"],
+				event["shiftKey"],
+				event["metaKey"],
+				false
+		);
+		wnd.document.dispatchEvent( e );
+	}
+}
+
+Test.AnotherWay._print_counter_result=function( url, msg, milliseconds, style )
+{
+	return Test.AnotherWay._print_result( url, msg+"<span class=\"counter\">"+(milliseconds/1000).toFixed()+"</span>", style, null );
+}
+
+Test.AnotherWay._g_result_count=0; // for assigning unique ids to result paragraphs
+
+// number of pages tested
+Test.AnotherWay._g_ok_pages=0;
+Test.AnotherWay._g_fail_pages=0;
+
+Test.AnotherWay._print_result=function( url, msg, style, test_objects )
+{
+	var results=document.getElementById( "results" );
+	var r=results.appendChild( document.createElement( "p" ) );
+	r.id="result"+Test.AnotherWay._g_result_count;
+	++Test.AnotherWay._g_result_count;
+	r.onclick=Test.AnotherWay._toggle_detail;
+	var text="<span class=\"bullet\">&nbsp;&nbsp;&nbsp;</span>&nbsp;";
+	if( url!="" ) {
+		text+=url+":  ";
+	}
+	if( msg!=null ) {
+		text+=msg;
+	}
+	if( test_objects!=null ) {
+		// compose summary and detail texts
+		var total_ok=0;
+		var total_detail_ok=0;
+		var total_fail=0;
+		var total_detail_fail=0;
+		var no_plan=0;
+
+		var detail=results.appendChild( document.createElement( "div" ) );
+
+		if( r.id.match( /^result(\d+)$/ ) ) {
+			detail.id="result_detail"+RegExp.$1;
+		}
+
+		for( var i=0; i<test_objects.length; ++i ) {
+			var o=test_objects[i];
+			var p;
+			var p_text;
+			p=document.createElement( "P" );
+			Test.AnotherWay._set_css_class( p, "result_detail" );
+			p_text=o.name;
+			if( o.n_fail>0 || o.exception || (o.n_plan!=null && o.n_plan!=o.n_ok+o.n_fail) || (o.n_plan==null && o.n_ok==0 && o.n_fail==0)) {
+				++total_fail;
+				p_text+=" <span class=\"fail\">";
+				if( o.n_plan!=null && o.n_plan!=o.n_ok+o.n_fail) {
+					p_text+="planned "+o.n_plan+" assertions but got "+(o.n_ok+o.n_fail)+"; ";
+				}
+				if(o.n_plan==null && o.n_ok==0 && o.n_fail==0) {
+					p_text+="test did not output anything";
+				}else {
+					p_text+=" fail "+o.n_fail;
+				}
+				p_text+="</span>";
+			}else {
+				++total_ok;
+			}
+			p_text+=" ok "+o.n_ok;
+			if( o.n_plan==null ) {
+				no_plan=1;
+				p_text+=" <span class=\"warning\">no plan</span>";
+			}
+			p.innerHTML=p_text;
+			detail.appendChild( p );
+			if( o.exception ) {
+				p=document.createElement( "P" );
+				Test.AnotherWay._set_css_class( p, "result_exception_detail" );
+				p.innerHTML="<span class=\"fail\">exception:</span> "+o.exception;
+				detail.appendChild( p );
+				p=document.createElement( "P" );
+				Test.AnotherWay._set_css_class( p, "result_exception_stack_detail" );
+				p.innerHTML=o.exception_stack.join( "<br/>" );
+				detail.appendChild( p );
+			}
+			for( var ii=0; ii<o.assertions.length; ++ii ) {
+				var oo=o.assertions[ii];
+				var status=oo.ok ? "ok" : "<span class=\"fail\">fail</span>";
+				p=document.createElement( "P" );
+				Test.AnotherWay._set_css_class( p, "result_micro_detail" );
+				p.innerHTML=status;
+				p.appendChild( document.createTextNode( " "+oo.name ) );
+				detail.appendChild( p );
+			}
+			total_detail_ok+=o.n_ok;
+			total_detail_fail+=o.n_fail;
+		}
+		if( total_fail || total_detail_fail ) {
+			text+=" fail "+total_fail;
+		}
+		text+=" ok "+total_ok+" (detailed:";
+		if( total_fail || total_detail_fail ) {
+			text+=" fail "+total_detail_fail;
+		}
+		text+=" ok "+total_detail_ok+")";
+		if( no_plan ) {
+			text+=" <span class=\"warning\">no plan</span>";
+		}
+		style= total_fail==0 ? "ok" : "fail";
+		detail.style.display= style=="fail" ? "block" : "none";
+		detail.style.cursor="text";
+	}
+	if( style!=null ) {
+		Test.AnotherWay._set_css_class( r, style );
+		if( style=="ok" ) {
+			++Test.AnotherWay._g_ok_pages;
+		}else if( style=="fail" || style=="badtest" ) {
+			++Test.AnotherWay._g_fail_pages;
+		}
+		var pages_total="";
+		if( Test.AnotherWay._g_fail_pages>0 ) {
+			pages_total+=" fail "+Test.AnotherWay._g_fail_pages;
+		}
+		pages_total+=" ok "+Test.AnotherWay._g_ok_pages;
+		Test.AnotherWay._update_results_total( pages_total );
+	}
+	r.innerHTML=text;
+	if( results.scrollHeight!=null && results.scrollTop!=null && results.offsetHeight!=null ) {
+		results.scrollTop=results.scrollHeight-results.offsetHeight;
+	}
+	// when test_objects is not null, the results are final - good time to clean up
+	if( test_objects!=null ) {
+		for( var i=0; i<test_objects.length; ++i ) {
+			var actions=test_objects[i].delay_actions;
+			for( var action_i=0; action_i<actions.length; ++action_i ) {
+				var action=actions[action_i];
+				if( action.action_kind=="window" && action.wnd_wnd!=null && !action.wnd_no_close ) {
+					action.wnd_wnd.close();
+					action.wnd_wnd=null;
+				}
+			}
+		}
+	}
+	return r;
+}
+Test.AnotherWay._unprint_result=function( child )
+{
+	var results=document.getElementById( "results" );
+	results.removeChild( child );
+}
+Test.AnotherWay._toggle_detail=function()
+{
+	if( this.id.match( /^result(\d+)$/ ) ) {
+		var detail=document.getElementById( "result_detail"+RegExp.$1 );
+		if( detail!=null ) {
+			if( detail.style.display=="none" ) {
+				detail.style.display="block";
+			}else if( detail.style.display=="block" ) {
+				detail.style.display="none";
+			}
+		}
+	}
+}
+Test.AnotherWay._update_msg_counter=function( msg, text )
+{
+	for( var i=0; i<msg.childNodes.length; ++i ) {
+		var item=msg.childNodes[i];
+		if( item.nodeName=="SPAN" && Test.AnotherWay._get_css_class( item )=="counter" ) {
+			item.innerHTML=text;
+		}
+	}
+}
+Test.AnotherWay._update_results_total=function( msg )
+{
+	var total=document.getElementById( "total" );
+	if( total ) {
+		total.innerHTML=msg;
+	}
+}
+Test.AnotherWay._results_clear_onclick=function()
+{
+	var results=document.getElementById( "results" );
+	results.innerHTML="";
+	Test.AnotherWay._update_results_total( "" );
+	Test.AnotherWay._g_ok_pages=0;
+	Test.AnotherWay._g_fail_pages=0;
+	var debug=document.getElementById( "debug" );
+	debug.innerHTML="";
+}
+
+Test.AnotherWay._get_css_class=function( o )
+{
+	var c=o.getAttribute( "className" );
+	if( c==null || c=="" ) {
+		c=o.getAttribute( "class" );
+	}
+	return c;
+}
+Test.AnotherWay._set_css_class=function( o, css_class )
+{
+	o.setAttribute( "className", css_class );
+	o.setAttribute( "class", css_class );
+}
+
+Test.AnotherWay._tab_onclick=function()
+{
+	var tab=this;
+	var tabs=[ document.getElementById( "debug_tab" ), document.getElementById( "results_tab" ) ];
+	var panes=[ document.getElementById( "debug" ), document.getElementById( "results" ) ];
+	for( var i=0; i<tabs.length; ++i ) {
+		if( tab==tabs[i] ) {
+			Test.AnotherWay._set_css_class( tabs[i], "active_tab" );
+			panes[i].style.display="block";
+		}else {
+			Test.AnotherWay._set_css_class( tabs[i], "inactive_tab" );
+			panes[i].style.display="none";
+		}
+	}
+}
+Test.AnotherWay._tab_mouseover=function()
+{
+	if( Test.AnotherWay._get_css_class( this )=="inactive_tab" ) {
+		Test.AnotherWay._set_css_class( this, "inactive_mouseover_tab" );
+	}
+}
+Test.AnotherWay._tab_mouseout=function()
+{
+	if( Test.AnotherWay._get_css_class( this )=="inactive_mouseover_tab" ) {
+		Test.AnotherWay._set_css_class( this, "inactive_tab" );
+	}
+}
+
+// recording mouse input
+Test.AnotherWay._record_check_onfocus=function()
+{
+	var o=this;
+	var check_select=o.type!="text";
+	var div=document.getElementById( "record_div" );
+	var inputs=div.getElementsByTagName( "input" );
+	for( var i=0; i<inputs.length; ++i ) {
+		var input=inputs[i];
+		if( input.type=="radio" ) {
+			if( input.value=="select" ) {
+				input.checked=check_select;
+			}else if( input.value=="input" ) {
+				input.checked=!check_select;
+			}
+		}
+	}
+}
+
+Test.AnotherWay._g_no_record_msg=null; // not null - recording is unavailable
+Test.AnotherWay._g_record_timeout_cnt=0; // opening window for a page for recording
+Test.AnotherWay._g_record_url=null;
+Test.AnotherWay._g_record_wnd=null;
+Test.AnotherWay._g_record_random_id=null; // added to element ids of record_control div so that they do not clash with ids already in the page for which input is recorded
+Test.AnotherWay._g_record_keydown=null; // recording control - which key is down
+Test.AnotherWay._g_record_ctrl_keydown=false;
+Test.AnotherWay._g_record_shift_keydown=false;
+Test.AnotherWay._g_record_control_visible=true; // recording control ui state
+Test.AnotherWay._g_record_started;
+Test.AnotherWay._g_record_paused;
+Test.AnotherWay._g_record_include_mousemove=false;
+Test.AnotherWay._g_record_start_time; // for time references
+Test.AnotherWay._g_record_pause_start_time;
+Test.AnotherWay._g_record_update_time_interval; // showing time in the control ui
+Test.AnotherWay._g_record_waiting_for_results=false; // waiting for results window to open
+Test.AnotherWay._g_record_events; // recorded events
+Test.AnotherWay._g_record_under_cursor; // track element under cursor
+Test.AnotherWay._g_record_checkpoint_count; // for checkpoint numbering
+Test.AnotherWay._g_record_mouse_over_record_control; // for avoiding record control highlight on mouseover
+Test.AnotherWay._g_record_highlighted_element={ element: null, x: null, y: null };
+
+Test.AnotherWay._record_control_get_element=function( id )
+{
+	if( Test.AnotherWay._g_record_wnd!=null && Test.AnotherWay._g_record_wnd.document!=null ) {
+		return Test.AnotherWay._g_record_wnd.document.getElementById( id+Test.AnotherWay._g_record_random_id );
+	}else {
+		return null;
+	}
+}
+Test.AnotherWay._record_start_onclick=function() // "record" button on the run_tests.html: open a window for a page for which input is recorded
+{
+	if( Test.AnotherWay._g_no_record_msg!=null ) {
+		alert( Test.AnotherWay._g_no_record_msg );
+		return;
+	}
+	if( Test.AnotherWay._g_record_timeout_cnt>0
+	    || (Test.AnotherWay._g_record_wnd!=null && (Test.AnotherWay._g_record_wnd.closed!=null && !Test.AnotherWay._g_record_wnd.closed)) ) { // in opera, closed is null.
+		alert( "there is already window opened for recording input for a page "+Test.AnotherWay._g_record_url );
+		return;
+	}
+	var div=document.getElementById( "record_div" );
+	var inputs=div.getElementsByTagName( "input" );
+	var url=null;
+	for( var i=0; i<inputs.length; ++i ) {
+		var input=inputs[i];
+		if( input.type=="radio" ) {
+			if( input.value=="select" && input.checked ) {
+				var index=document.getElementById( "record_select" ).selectedIndex;
+				if( index>0 ) {
+					url=Test.AnotherWay._g_test_page_urls[index-1].url;
+				}
+			}else if( input.value=="input" && input.checked ) {
+				url=document.getElementById( "record_input" ).value;
+			}
+		}
+	}
+	if( url!=null ) {
+		Test.AnotherWay._g_record_url=url;
+		Test.AnotherWay._g_record_wnd=window.open( url, "_blank" );
+		if( Test.AnotherWay._g_record_wnd==null ) {
+			alert( "unable to open new window for a page: "+url );
+		}else {
+			Test.AnotherWay._g_record_timeout_cnt=50;
+			setTimeout( Test.AnotherWay._record_window_timeout, 100 );
+		}
+	}
+}
+Test.AnotherWay._record_window_timeout=function()
+{
+	if( Test.AnotherWay._is_url_loaded( Test.AnotherWay._g_record_url, Test.AnotherWay._g_record_wnd ) ) {
+		Test.AnotherWay._record_window_setup( Test.AnotherWay._g_record_wnd );
+	}else {
+		if( --Test.AnotherWay._g_record_timeout_cnt>0 ) {
+			setTimeout( Test.AnotherWay._record_window_timeout, 100 );
+		}else {
+			alert( "timeout expired while opening new window for a page: "+Test.AnotherWay._g_record_url );
+			Test.AnotherWay._g_record_wnd=null;
+			Test.AnotherWay._g_record_url=null;
+			Test.AnotherWay._g_record_timeout_cnt=0;
+		}
+	}
+}
+Test.AnotherWay._record_control_randomize_id=function( e, r )
+{
+	if( e.id!="" ) {
+		e.id=e.id+r;
+	}
+	for( var c=e.firstChild; c!=null; c=c.nextSibling ) {
+		Test.AnotherWay._record_control_randomize_id( c, r );
+	}
+}
+Test.AnotherWay._record_window_setup=function( wnd ) // insert recording control into the page for which input is recorded
+{
+	Test.AnotherWay._g_record_timeout_cnt=0;
+	var this_div=document.getElementById( "record_control" );
+	var record_control=wnd.document.importNode( this_div, true );
+	Test.AnotherWay._g_record_random_id=(1000*Math.random()).toFixed();
+	Test.AnotherWay._record_control_randomize_id( record_control, Test.AnotherWay._g_record_random_id );
+	Test.AnotherWay._g_record_control_visible=true;
+	Test.AnotherWay._g_record_started=false;
+	Test.AnotherWay._g_record_paused=false;
+	Test.AnotherWay._g_record_checkpoint_count=0;
+	Test.AnotherWay._g_record_mouse_over_record_control=false;
+	var doc=wnd.document;
+	doc.body.appendChild( record_control );
+	// opera sans-serif font is different
+	if( window.opera ) {
+		cursor_over_indicator=Test.AnotherWay._record_control_get_element( "record_cursor_over" );
+		cursor_over_indicator.style.width="18em";
+		cursor_over_indicator.style.height="2em";
+		cursor_over_indicator.style.fontSize="7pt";
+	}
+	doc.addEventListener( "keydown", Test.AnotherWay._record_control_keydown, true );
+	doc.addEventListener( "keyup", Test.AnotherWay._record_control_keyup, true );
+//	doc.addEventListener( "keypress", Test.AnotherWay._record_event, true ); // replaying is not supported by any known browser
+
+	doc.body.addEventListener( "mousemove", Test.AnotherWay._record_on_mousemove, true );
+	doc.body.addEventListener( "click", Test.AnotherWay._record_event, true );
+	doc.body.addEventListener( "mouseover", Test.AnotherWay._record_event, true );
+	doc.body.addEventListener( "mouseout", Test.AnotherWay._record_event, true );
+	doc.body.addEventListener( "mousedown", Test.AnotherWay._record_event, true );
+	doc.body.addEventListener( "mouseup", Test.AnotherWay._record_event, true );
+}
+Test.AnotherWay._record_control_key_disabled=function( k )
+{
+	if( k=="c" ) {
+		return !Test.AnotherWay._g_record_started;
+	}else if( k=="p" ) {
+		return !Test.AnotherWay._g_record_started;
+	}else if( k=="s" ) {
+		return Test.AnotherWay._g_record_waiting_for_results;
+	}else {
+		return false;
+	}
+}
+
+Test.AnotherWay._record_control_update_ui=function()
+{
+	var keydown_color="#fff";
+	var disabled_color="#aaa";
+	var button_color="#adf";
+	var active_color="#fdf";
+
+	var display={};
+	display[false]="none";
+	display[true]="inline";
+
+	var s_button=Test.AnotherWay._record_control_get_element( "record_s" );
+	var record_on=Test.AnotherWay._record_control_get_element( "record_on" );
+	var record_off=Test.AnotherWay._record_control_get_element( "record_off" );
+
+	s_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "s" ) ? disabled_color
+		: Test.AnotherWay._g_record_keydown=="s" ? keydown_color : Test.AnotherWay._g_record_started ? active_color : button_color;
+	record_on.style.display=display[!Test.AnotherWay._g_record_started];
+	record_off.style.display=display[Test.AnotherWay._g_record_started];
+
+	var h_button=Test.AnotherWay._record_control_get_element( "record_h" );
+	h_button.style.backgroundColor= Test.AnotherWay._g_record_keydown=="h" ? keydown_color : button_color;
+
+	var p_button=Test.AnotherWay._record_control_get_element( "record_p" );
+	var record_pause_on=Test.AnotherWay._record_control_get_element( "record_pause_on" );
+	var record_pause_off=Test.AnotherWay._record_control_get_element( "record_pause_off" );
+	p_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "p" ) ? disabled_color
+		: Test.AnotherWay._g_record_keydown=="p" ? keydown_color : Test.AnotherWay._g_record_paused ? active_color : button_color;
+	record_pause_on.style.display=display[!Test.AnotherWay._g_record_paused];
+	record_pause_off.style.display=display[Test.AnotherWay._g_record_paused];
+
+	var m_button=Test.AnotherWay._record_control_get_element( "record_m" );
+	var record_include_mousemove=Test.AnotherWay._record_control_get_element( "record_include_mousemove" );
+	var record_omit_mousemove=Test.AnotherWay._record_control_get_element( "record_omit_mousemove" );
+	m_button.style.backgroundColor= Test.AnotherWay._g_record_keydown=="m" ? keydown_color : Test.AnotherWay._g_record_include_mousemove ? active_color : button_color;
+	record_include_mousemove.style.display=display[!Test.AnotherWay._g_record_include_mousemove];
+	record_omit_mousemove.style.display=display[Test.AnotherWay._g_record_include_mousemove];
+
+	var c_button=Test.AnotherWay._record_control_get_element( "record_c" );
+	c_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "c" ) ? disabled_color
+		: Test.AnotherWay._g_record_keydown=="c" ? keydown_color : button_color;
+
+	var record_indicator=Test.AnotherWay._record_control_get_element( "record_indicator" );
+	record_indicator.style.display=display[Test.AnotherWay._g_record_started];
+
+	var pause_indicator=Test.AnotherWay._record_control_get_element( "record_pause_indicator" );
+	pause_indicator.style.display=display[Test.AnotherWay._g_record_paused];
+
+	var record_control=Test.AnotherWay._record_control_get_element( "record_control" );
+	record_control.style.display= Test.AnotherWay._g_record_control_visible ? "block" : "none";
+
+	var shift_button=Test.AnotherWay._record_control_get_element( "record_shift_key" );
+	shift_button.style.backgroundColor= Test.AnotherWay._g_record_shift_keydown ? keydown_color : button_color;
+
+	var ctrl_button=Test.AnotherWay._record_control_get_element( "record_ctrl_key" );
+	ctrl_button.style.backgroundColor= Test.AnotherWay._g_record_ctrl_keydown ? keydown_color : button_color;
+}
+Test.AnotherWay._record_format_time=function( t )
+{
+	t=new Date( t );
+	var m=t.getMinutes();
+	var s=t.getSeconds();
+	var str= m==0 ? "" : m+"m ";
+	str+=s+"s.";
+	return str;
+}
+Test.AnotherWay._record_control_update_time=function()
+{
+	var time_display=Test.AnotherWay._record_control_get_element( "record_time" );
+	if( time_display!=null ) {
+		time_display.innerHTML=Test.AnotherWay._record_format_time( (new Date()).getTime()-Test.AnotherWay._g_record_start_time );
+	}
+}
+Test.AnotherWay._record_control_update_highlight=function( elem, style, event )
+{
+	if( elem==null ) {
+		Test.AnotherWay._record_highlight_border( null );
+	}else {
+		var pos=Test.AnotherWay._get_page_coords( elem );
+		if( style=="ball" || elem!=Test.AnotherWay._g_record_highlighted_element.element || pos.x!=Test.AnotherWay._g_record_highlighted_element.x || pos.y!=Test.AnotherWay._g_record_highlighted_element.y ) {
+			Test.AnotherWay._g_record_highlighted_element={ element: elem, x: pos.x, y: pos.y };
+			Test.AnotherWay._record_highlight_border( elem, style, event );
+		}
+	}
+}
+Test.AnotherWay._record_decode_key=function( event )
+{
+	var k=null;
+	if( event==null ) {
+		k=Test.AnotherWay._g_record_wnd.event.keyCode;
+	}else {
+		k=event.which;
+	}
+	if( k==83 ) {
+		return "s";
+	}else if( k==72 ) {
+		return "h";
+	}else if( k==73 ) {
+		return "i";
+	}else if( k==80 ) {
+		return "p";
+	}else if( k==67 ) {
+		return "c";
+	}else if( k==77 ) {
+		return "m";
+	}else if( k==16 ) {
+		return "shift";
+	}else if( k==17 ) {
+		return "ctrl";
+	}else if( k==18 ) {
+		return "alt";
+	}else if( k==19 ) {
+		return "pause";
+	}else if( k==123 ) {
+		return "f12";
+	}
+	return "";
+}
+Test.AnotherWay._record_control_keydown=function( event )
+{
+	var handled=false;
+	var k=Test.AnotherWay._record_decode_key( event );
+	if( k=="shift" ) {
+		Test.AnotherWay._g_record_shift_keydown=true;
+	}else if( k=="ctrl" ) {
+		Test.AnotherWay._g_record_ctrl_keydown=true;
+	}else if( k!="" && (Test.AnotherWay._g_record_keydown==null || Test.AnotherWay._g_record_keydown==k) ) {
+		if( Test.AnotherWay._g_record_ctrl_keydown && Test.AnotherWay._g_record_shift_keydown && !Test.AnotherWay._record_control_key_disabled( k ) ) {
+			Test.AnotherWay._g_record_keydown=k;
+			handled=true;
+		}
+	}else {
+		Test.AnotherWay._g_record_keydown="";
+	}
+	Test.AnotherWay._record_control_update_ui();
+	if( !handled ) {
+//		Test.AnotherWay._record_event( event ); // replaying is not supported in any known browser
+	}
+	return;
+}
+Test.AnotherWay._record_control_keyup=function( event )
+{
+	var handled=false;
+	var k=Test.AnotherWay._record_decode_key( event );
+	if( k=="shift" ) {
+		Test.AnotherWay._g_record_shift_keydown=false;
+	}else if( k=="ctrl" ) {
+		Test.AnotherWay._g_record_ctrl_keydown=false;
+	}else if( k!="" && k==Test.AnotherWay._g_record_keydown && Test.AnotherWay._g_record_ctrl_keydown && Test.AnotherWay._g_record_shift_keydown  ) {
+		if( k=="s" ) {
+			Test.AnotherWay._g_record_started=!Test.AnotherWay._g_record_started;
+			if( Test.AnotherWay._g_record_started ) {
+				Test.AnotherWay._g_record_events=[];
+				Test.AnotherWay._g_record_start_time=(new Date()).getTime();
+				Test.AnotherWay._record_control_update_time();
+				Test.AnotherWay._g_record_update_time_interval=window.setInterval( Test.AnotherWay._record_control_update_time, 200 );
+			}else {
+				Test.AnotherWay._record_control_update_highlight( null );
+				if( !Test.AnotherWay._g_record_paused ) {
+					window.clearInterval( Test.AnotherWay._g_record_update_time_interval );
+				}
+				Test.AnotherWay._g_record_waiting_for_results=true;
+				// open a new window for self, pass a parameter to dump recorded events as javascript code there
+				// (the easiest way to obtain a document from the same origin, so it's writable, is to open this same page again)
+				Test.AnotherWay._g_record_paused=false;
+				var loc=window.location;
+				loc=loc.protocol+"//"+loc.host+loc.pathname+"?recording_results="+Test.AnotherWay._g_record_random_id;
+				if( window.open( loc, "_blank" )==null ) {
+					alert( "unable to open new window for results" );
+				}
+			}
+			handled=true;
+		}else if( k=="h" ) {
+			Test.AnotherWay._g_record_control_visible=!Test.AnotherWay._g_record_control_visible;
+			handled=true;
+		}else if( k=="p" ) {
+			Test.AnotherWay._g_record_paused=!Test.AnotherWay._g_record_paused;
+			if( Test.AnotherWay._g_record_paused ) {
+				Test.AnotherWay._g_record_pause_start_time=(new Date()).getTime();
+				if( Test.AnotherWay._g_record_started ) {
+					window.clearInterval( Test.AnotherWay._g_record_update_time_interval );
+				}
+				Test.AnotherWay._record_control_update_highlight( null );
+			}else {
+				var pause_duration=(new Date()).getTime()-Test.AnotherWay._g_record_pause_start_time;
+				Test.AnotherWay._g_record_start_time+=pause_duration;
+				Test.AnotherWay._g_record_update_time_interval=window.setInterval( Test.AnotherWay._record_control_update_time, 200 );
+			}
+			handled=true;
+		}else if( k=="m" ) {
+			Test.AnotherWay._g_record_include_mousemove=!Test.AnotherWay._g_record_include_mousemove;
+			handled=true;
+		}else if( k=="c" ) {
+			var o=Test.AnotherWay._record_checkpoint();
+			Test.AnotherWay._record_display_checkpoint( o );
+			Test.AnotherWay._record_flash_border( "#24d" );
+			handled=true;
+		}
+	}
+	Test.AnotherWay._g_record_keydown=null;
+	Test.AnotherWay._record_control_update_ui();
+	if( !handled ) {
+//		Test.AnotherWay._record_event( event ); // replaying is not supported in any known browser
+	}
+	return;
+}
+Test.AnotherWay._record_html_node_path=function( node )
+{
+	if( node==null ) {
+		return null;
+	}
+	var path=[];
+	while( true ) {
+		if( node.id!=null && node.id!="" ) {
+			path.unshift( "#"+node.id+" "+node.nodeName );
+			break;
+		}else {
+			var parent_node=node.parentNode;
+			if( parent_node==null ) {
+				return []; // no BODY up the path - this node is screwed (browsers differ in what's above the body), discard
+			}else {
+				var i=0;
+				var found=false;
+				for( var child=parent_node.firstChild; child!=null; child=child.nextSibling ) {
+					if( child==node ) {
+						found=true;
+						break;
+					}
+					if( child.nodeType==1 ) { // count only HTML element nodes
+						++i;
+					}
+				}
+				if( !found ) {
+					i=-1;
+				}
+				path.unshift( i+" "+node.nodeName );
+				if( parent_node.nodeName=="BODY" || parent_node.nodeName=="body" ) {
+					break;
+				}
+				node=parent_node;
+			}
+		}
+	}
+	return path;
+}
+Test.AnotherWay._record_node_path_to_string=function( path )
+{
+	var s="";
+	if( path!=null ) {
+		for( var i=0; i<path.length; ++i ) {
+			s+= i==0 ? "" : ", ";
+			var elem=path[i].split( " " );
+			if( elem[0].charAt( 0 )=="#" ) {
+				s+=elem[1]+" "+elem[0];
+			}else {
+				s+=elem[1]+" ["+elem[0]+"]";
+			}
+		}
+	}
+	return s;
+}
+Test.AnotherWay._record_node_path_to_node=function( path_str, doc )
+{
+	if( path_str==null ) {
+		return null;
+	}
+	var path=path_str.split( "," );
+	var node=doc.body;
+	for( var i=0; i<path.length; ++i ) {
+		var node_i=path[i].split( " " )[0];
+		if( node_i.charAt( 0 )=="#" ) {
+			node=doc.getElementById( node_i.substring( 1 ) );
+		}else {
+			if( node_i<0 || node_i>=node.childNodes.length ) {
+				node=null;
+			}else {
+				node=node.firstChild;
+				while( node!=null ) {
+					if( node.nodeType==1 ) {  // count only HTML element nodes
+						if( node_i==0 ) {
+							break;
+						}
+						--node_i;
+					}
+					node=node.nextSibling;
+				}
+			}
+		}
+		if( node==null ) {
+			return null;
+		}
+	}
+	return node;
+}
+Test.AnotherWay._record_control_contains_id=function( s )
+{
+	return s.match( /^#record_[\w_]+/ ) && s.match( Test.AnotherWay._g_record_random_id );
+}
+Test.AnotherWay._record_checkpoint=function()
+{
+	var o={ type: "_checkpoint", time: (new Date()).getTime()-Test.AnotherWay._g_record_start_time, which: Test.AnotherWay._g_record_checkpoint_count++,
+			target: Test.AnotherWay._record_html_node_path( Test.AnotherWay._g_record_under_cursor ) };
+	Test.AnotherWay._g_record_events.push( o );
+	return o;
+}
+Test.AnotherWay._record_event=function( event )
+{
+	var unneeded=["rangeOffset","eventPhase","timeStamp","isTrusted","popupWindowFeatures","rangeOffset"];
+	if( Test.AnotherWay._g_record_started && !Test.AnotherWay._g_record_paused ) {
+		var o={};
+		for( var n in event ) {
+			var needed=!n.match( /^[A-Z0-9_]+$/ );
+			if( needed ) {
+				for( var ui=0; ui<unneeded.length; ++ui ) {
+					if( unneeded[ui]==n ) {
+						needed=false;
+						break;
+					}
+				}
+				if( needed ) {
+					var value=event[n];
+					if( typeof( value )!="object" && typeof( value )!="function" ) {
+						o[n]=value;
+					}else if( n=="target" || n=="relatedTarget" ) {
+						o[n]=Test.AnotherWay._record_html_node_path( value );
+					}
+				}
+			}
+		}
+		o["time"]=(new Date()).getTime()-Test.AnotherWay._g_record_start_time;
+		var over_record_control= o["target"]!=null && o["target"][0]!=null && Test.AnotherWay._record_control_contains_id( o["target"][0] );
+		if( !over_record_control ) {
+			Test.AnotherWay._g_record_events.push( o );
+		}
+	}
+	return true;
+}
+Test.AnotherWay._record_on_mousemove=function( event )
+{
+	var path=Test.AnotherWay._record_html_node_path( event.target );
+	var new_mouse_over_record_control= path!=null && path[0]!=null && Test.AnotherWay._record_control_contains_id( path[0] );
+	if( new_mouse_over_record_control!=Test.AnotherWay._g_record_mouse_over_record_control ) {
+		Test.AnotherWay._g_record_mouse_over_record_control=new_mouse_over_record_control;
+		Test.AnotherWay._record_control_update_ui();
+	}
+	if( event.target!=null && event.target!=Test.AnotherWay._g_record_under_cursor ) {
+		Test.AnotherWay._g_record_under_cursor=event.target;
+		var s="";
+		if( path==null || path[0]==null || !Test.AnotherWay._record_control_contains_id( path[0] ) ) {
+			s=Test.AnotherWay._record_node_path_to_string( path );
+		}
+		if( s=="" ) {
+			s="&nbsp;";
+		}
+		var cursor_over_indicator=Test.AnotherWay._record_control_get_element( "record_cursor_over" );
+		cursor_over_indicator.innerHTML=s;
+	}
+
+	var highlight_element=null;
+	if( !Test.AnotherWay._g_record_mouse_over_record_control && Test.AnotherWay._g_record_started && !Test.AnotherWay._g_record_paused ) {
+		highlight_element=event.target;
+	}
+	// highlight border disabled on recording - it causes page to scroll, issuing spurious mouseover/mouseout event
+	//Test.AnotherWay._record_control_update_highlight( highlight_element, "border" );
+
+	if( Test.AnotherWay._g_record_include_mousemove ) {
+		Test.AnotherWay._record_event( event );
+	}
+	return true;
+}
+Test.AnotherWay._record_display_checkpoint=function( o )
+{
+	var checkpoints_div=Test.AnotherWay._record_control_get_element( "record_checkpoints" );
+	var p=checkpoints_div.appendChild( checkpoints_div.ownerDocument.createElement( "div" ) );
+	p.style.marginTop="3px";
+	p.style.font="normal normal 8pt sans-serif";
+	p.style.color="#000";
+	p.style.textAligh="left";
+	p.style.position="relative";
+	p.style.width="100%";
+	var checkpoint_text="";
+	checkpoint_text+="#"+(o.which+1);
+	checkpoint_text+="  "+Test.AnotherWay._record_format_time( o.time );
+	if( o.target!=null ) {
+		checkpoint_text+=Test.AnotherWay._record_node_path_to_string( o.target );
+	}
+	p.appendChild( p.ownerDocument.createTextNode( checkpoint_text ) );
+}
+Test.AnotherWay._record_save_results=function( doc )
+{
+	// strange, but DOM-style append does not work here in opera 8.
+	var append=function( s ) { doc.write( "<div>"+s+"</div>" ); };
+	append( "/* paste this data into your javascript and pass it as an argument to replay_events method */" );
+	append( "{ checkpoints: [" );
+	var first_checkpoint=true;
+	for( var i=0; i<Test.AnotherWay._g_record_events.length; ++i ) {
+		var o=Test.AnotherWay._g_record_events[i];
+		if( o.type=="_checkpoint" ) {
+			var str= first_checkpoint ? "" : "}, ";
+			str+="function( tst, wnd ) { // #"+o.which+" time "+Test.AnotherWay._record_format_time( o.time )+" cursor was over "+Test.AnotherWay._record_node_path_to_string( o.target );
+			append( str );
+			first_checkpoint=false;
+		}
+	}
+	if( !first_checkpoint ) {
+		append( "}" );
+	}
+	append( "], events: [ " );
+	var prev_time=0;
+	for( var i=0; i<Test.AnotherWay._g_record_events.length; ++i ) {
+		var o=Test.AnotherWay._g_record_events[i];
+		var s="";
+		s+= "{";
+		var n_first=true;
+		for( var n in o ) {
+			if( n=="time" ) { // convert to relative time
+				var cur_time=o[n]-0;
+				o[n]=cur_time-prev_time;
+				prev_time=cur_time;
+			}
+			s+=n_first ? n : ", "+n;
+			s+=":";
+			if( o[n]==null ) {
+				s+="null";
+			}else {
+				s+="\""+o[n]+"\"";
+			}
+			n_first=false;
+		}
+		s+= i==Test.AnotherWay._g_record_events.length-1 ? "}" : "},";
+		append( s );
+	}
+	append( "] }" );
+	append( ";" );
+}
+
+Test.AnotherWay._g_record_border; // border highlighting element under cursor
+Test.AnotherWay._g_record_border_flashes=[]; // array of { color: color, timeout: milliseconds }
+Test.AnotherWay._g_record_border_flashing=false;
+Test.AnotherWay._g_record_border_normal_color="#d4b";
+Test.AnotherWay._record_flash_border_timeout=function()
+{
+	var color=Test.AnotherWay._g_record_border_normal_color;
+	var timeout=null;
+	if( Test.AnotherWay._g_record_border_flashes.length!=0 ) {
+		color=Test.AnotherWay._g_record_border_flashes[0].color;
+		timeout=Test.AnotherWay._g_record_border_flashes[0].timeout;
+		Test.AnotherWay._g_record_border_flashes.splice( 0, 1 );
+	}
+	if( Test.AnotherWay._g_record_border!=null ) {
+		for( var i=0; i<Test.AnotherWay._g_record_border.length; ++i ) {
+			Test.AnotherWay._g_record_border[i].style.backgroundColor=color;
+		}
+	}
+	if( timeout!=null ) {
+		setTimeout( Test.AnotherWay._record_flash_border_timeout, timeout );
+	}else {
+		Test.AnotherWay._g_record_border_flashing=false;
+	}
+}
+Test.AnotherWay._get_page_coords=function( elm )
+{
+	var point = { x: 0, y: 0 };
+	while( elm )  {
+		point.x+=elm.offsetLeft;
+		point.y+=elm.offsetTop;
+		elm=elm.offsetParent;
+	 }
+	return point;
+}
+Test.AnotherWay._set_page_coords=function( elm, x, y )
+{
+	var parent_coords={ x: 0, y: 0 };
+	if( elm.offsetParent )  {
+		parent_coords=Test.AnotherWay._get_page_coords( elm.offsetParent );
+	}
+	var new_x=x-parent_coords.x;
+	if( new_x<0 ) {
+		new_x=0;
+	}
+	elm.style.left=new_x+'px';
+	var new_y=y-parent_coords.y;
+	if( new_y<0 ) {
+		new_y=0;
+	}
+	elm.style.top=new_y+'px';
+}
+Test.AnotherWay._record_setup_highlight_positions=function( element, style, coords, positions )
+{
+	if( style=="border" ) {
+		var width=element.clientWidth;
+		var height=element.clientHeight;
+		var step=0;
+		var thickness=2;
+		var fudge_expand=4;
+		positions.push( { x: coords.x-step-thickness, y: coords.y-step-thickness, width: width+2*step+2*thickness+fudge_expand, height: thickness } );
+		positions.push( { x: coords.x+width+step+fudge_expand, y: coords.y-step-thickness, width: thickness, height: height+2*step+2*thickness+fudge_expand } );
+		positions.push( { x:positions[0].x, y:positions[0].y, width:positions[0].width, height:positions[0].height } );
+		positions.push( { x:positions[1].x, y:positions[1].y, width:positions[1].width, height:positions[1].height } );
+		positions[2].y+=height+thickness+2*step+fudge_expand;
+		positions[3].x-=width+thickness+2*step+fudge_expand;
+	}else if( style=="ball" ) {
+		positions.push( { x: coords.x+2, y: coords.y, width: 2, height: 6 } );
+		positions.push( { x: coords.x, y: coords.y+2, width: 6, height: 2 } );
+		positions.push( { x: coords.x+1, y: coords.y+1, width: 4, height: 4 } );
+	}
+}
+Test.AnotherWay._record_highlight_border=function( element, style, event ) // null - hide border
+{
+	if( element!=null ) {
+		if( Test.AnotherWay._g_record_border==null || Test.AnotherWay._g_record_border[0].ownerDocument!=element.ownerDocument ) {
+			Test.AnotherWay._g_record_border=[];
+			var n= style=="border" ? 4 : style=="ball" ? 3 : 0;
+			for( var i=0; i<4; ++i ) {
+				var b=element.ownerDocument.createElement( "div" );
+				b.style.position="absolute";
+				b.style.zIndex="1";
+				b.style.backgroundColor=Test.AnotherWay._g_record_border_normal_color;
+				element.ownerDocument.body.appendChild( b );
+				Test.AnotherWay._g_record_border.push( b );
+			}
+		}
+		var coords=null;
+		if( style=="border" ) {
+			coords=Test.AnotherWay._get_page_coords( element );
+		}else if( style=="ball" ) {
+			if( event!=null ) {
+				if( event.pageX!=null && event.pageY!=null ) {
+					coords={ x: event.pageX-0, y: event.pageY-0 };
+				}else if( event.clientX!=null && event.clientY!=null ) {
+					var doc=element.ownerDocument;
+					if( doc!=null ) {
+						coords={ x: (event.clientX-0)+doc.body.scrollLeft, y: (event.clientY-0)+doc.body.scrollTop };
+					}
+				}
+			}
+		}
+		if( coords!=null && element.clientWidth!=null && element.clientHeight!=null ) {
+			var positions=[];
+			Test.AnotherWay._record_setup_highlight_positions( element, style, coords, positions );
+			for( var i=0; i<positions.length; ++i ) {
+				var b=Test.AnotherWay._g_record_border[i];
+				var p=positions[i];
+				Test.AnotherWay._set_page_coords( b, p.x, p.y );
+				b.style.width=p.width+"px";
+				b.style.height=p.height+"px";
+				b.style.display="block";
+			}
+		}
+	}else {
+		if( Test.AnotherWay._g_record_border!=null ) {
+			for( var i=0; i<Test.AnotherWay._g_record_border.length; ++i ) {
+				Test.AnotherWay._g_record_border[i].style.display="none";
+			}
+		}
+	}
+}
+Test.AnotherWay._record_flash_border=function( color )
+{
+	if( Test.AnotherWay._g_record_border_flashing ) { //already
+		Test.AnotherWay._g_record_border_flashes.push( { color: Test.AnotherWay._g_record_border_normal_color, timeout:300 } );
+		Test.AnotherWay._g_record_border_flashes.push( { color: color, timeout:600 } );
+	}else {
+		Test.AnotherWay._g_record_border_flashing=true;
+		Test.AnotherWay._g_record_border_flashes.push( { color: color, timeout:600 } );
+		Test.AnotherWay._record_flash_border_timeout();
+	}
+}
+Test.AnotherWay._record_prepare_doc_for_results=function()
+{
+	document.open();
+	document.write( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" );
+	document.write( "<html><head><title> Input recording results</title>" );
+	document.write( "<style type=\"text/css\">" );
+	document.write( "body { font: normal normal smaller sans-serif; }" );
+	document.write( "div { margin-top: 3px; }" );
+	document.write( "</style></head><body>" );
+	// opera and mozilla disagree over who the opener is.
+	if( typeof( window.opener.Test )!="undefined" && typeof( window.opener.Test.AnotherWay )!="undefined" ) {
+		window.opener.Test.AnotherWay._record_save_results( document );
+		window.opener.Test.AnotherWay._g_record_waiting_for_results=false;
+		window.opener.Test.AnotherWay._record_control_update_ui();
+	}else if( typeof( window.opener.opener.Test  )!="undefined" && typeof( window.opener.opener.Test.AnotherWay )!="undefined" ) {
+		window.opener.opener.Test.AnotherWay._record_save_results( document );
+		window.opener.opener.Test.AnotherWay._g_record_waiting_for_results=false;
+		window.opener.opener.Test.AnotherWay._record_control_update_ui();
+	}
+	document.write( "</body>" );
+	document.close();
+}
+
+// global initialization
+onload=function()
+{
+	if( window.opera ) {
+		var good_opera=typeof( window.opera.version )=="function";
+		good_opera=good_opera && window.opera.version().match( /^\s*(\d+)/ );
+		good_opera=good_opera && RegExp.$1>=8;
+	}
+	var span=document.createElement( "SPAN" );
+	span.innerHTML="<!--[if IE]><br /><![endif]-"+"->";
+	var is_ie=span.getElementsByTagName( "BR" ).length>0;
+
+	Test.AnotherWay._g_test_iframe=window.frames.test_iframe;
+
+	var query_str=window.location.search;
+	if( query_str.charAt( 0 )=="?" ) {
+		query_str=query_str.substring( 1 );
+	}
+	var testlist_page="list-tests.html";
+	var auto_run=false;
+	if( query_str!="" ) {
+		var params=[query_str];
+		if( query_str.indexOf( ";" )!=-1 ) {
+			params=query_str.split( ";" );
+		}else if( query_str.indexOf( "&" )!=-1 ) {
+			params=query_str.split( "&" );
+		}
+		for( var param_i=0; param_i<params.length; ++param_i ) {
+			var param=params[param_i].split( "=" );
+			if( param[0]=="recording_results" ) {
+				if( window.opener!=null ) {
+					// we were told to show recording results - replace everything in the document with the results
+					Test.AnotherWay._record_prepare_doc_for_results();
+					return;
+				}
+			}else if( param[0]=="testpage" ) {
+				Test.AnotherWay._add_test_page_url( decodeURIComponent( param[1] ), "anotherway" );
+			}else if( param[0]=="jsantestpage" ) {
+				Test.AnotherWay._add_test_page_url( decodeURIComponent( param[1] ), "jsan" );
+			}else if( param[0]=="testlist" ) {
+				testlist_page=decodeURIComponent( param[1] );
+			}else if( param[0]=="testframe" ) {
+				if( window.opera && !good_opera ) {
+					Test.AnotherWay._show_error( "testframe parameter does not work in versions of Opera prior to 8.0. Sorry (pathches are welcome)." );
+					// Opera 7 barfs on attempt to access frame.frameElement.
+					// if someone knows a way to assign onload handler to that iframe in Opera 7
+					// without disrupting code that works in other browsers, patches are welcome.
+				}else {
+					var frame_path=param[1].split( "." );
+					var frame=top;
+					for( var frame_path_i=0; frame_path_i<frame_path.length; ++frame_path_i ) {
+						frame=frame[frame_path[frame_path_i]];
+					}
+					if( frame==null ) {
+						Test.AnotherWay._show_error( "unable to find frame specified for loading test pages: "+param[1] );
+					}else {
+						if( frame.frameElement!=null ) { // for the following assignement to onload to work, frameElement is required
+							frame=frame.frameElement;
+						}
+						Test.AnotherWay._g_test_iframe=frame;
+					}
+				}
+			}else if( param[0]=="testframe_no_clear" ) {
+				Test.AnotherWay._g_test_frame_no_clear=true;
+			}else if( param[0]=="run" ) {
+				auto_run=true;
+				if( param[1]=="all" ) {
+					Test.AnotherWay._g_pages_to_run="all";
+				}else {
+					if( Test.AnotherWay._g_pages_to_run==null || Test.AnotherWay._g_pages_to_run=="all" ) {
+						Test.AnotherWay._g_pages_to_run=[];
+					}
+					var pages=param[1].split( "," );
+					for( var i=0; i<pages.length; ++i ) {
+						Test.AnotherWay._g_pages_to_run.push( pages[i] );
+					}
+				}
+			}
+		}
+	}
+	if( Test.AnotherWay._g_test_page_urls.length==0 ) {  // if no individual pages were given on the command line, load the list
+		var result=Test.AnotherWay._set_iframe_location( window.frames["list_iframe"], testlist_page );
+		if( result.msg!=null ) {
+			Test.AnotherWay._show_error( result.msg );
+		}
+		Test.AnotherWay._g_run_on_list_load=auto_run;
+	}else {
+		Test.AnotherWay._g_run_on_main_load=auto_run;
+	}
+
+	var f=Test.AnotherWay._g_test_iframe;
+	try {
+		if( f.attachEvent!=null ) {
+			f.attachEvent( "onload", Test.AnotherWay._test_page_onload );
+		}else {
+			f.onload=Test.AnotherWay._test_page_onload;
+		}
+		if( Test.AnotherWay._g_test_iframe.nodeType!=null && Test.AnotherWay._g_test_iframe.contentWindow!=null ) { // it's iframe element, not the iframe. we need iframe.
+			Test.AnotherWay._g_test_iframe=Test.AnotherWay._g_test_iframe.contentWindow;
+		}
+	}catch(e) {
+		// ignore stupid opera error if the frame has onload handler assigned in the inline html
+	}
+	var handlers={
+		"run_all": { "onclick": Test.AnotherWay._run_all_onclick },
+		"run_selected": { "onclick": Test.AnotherWay._run_selected_onclick },
+		"unselect_all": { "onclick": Test.AnotherWay._unselect_all_onclick },
+		"record_select": { "onfocus": Test.AnotherWay._record_check_onfocus },
+		"record_input": { "onfocus": Test.AnotherWay._record_check_onfocus },
+		"record_start": { "onclick": Test.AnotherWay._record_start_onclick },
+		"clear_btn": { "onclick": Test.AnotherWay._results_clear_onclick },
+		"results_tab": { "onclick": Test.AnotherWay._tab_onclick, "onmouseover": Test.AnotherWay._tab_mouseover, "onmouseout": Test.AnotherWay._tab_mouseout },
+		"debug_tab": { "onclick": Test.AnotherWay._tab_onclick, "onmouseover": Test.AnotherWay._tab_mouseover, "onmouseout": Test.AnotherWay._tab_mouseout }
+	};
+	for( var hs in handlers ) {
+		var o=document.getElementById( hs );
+		if( o!=null ) {
+			for( var h in handlers[hs] ) {
+				o[h]=handlers[hs][h];
+			}
+		}else {
+			Test.AnotherWay._show_error( "unable to set "+h+" handler: id "+hs+" not found" );
+		}
+	}
+
+	if( window.opera && !good_opera ) {
+		Test.AnotherWay._g_no_record_msg="Input events recording and replaying is not available in opera versions prior to 8.0.";
+	}
+	if( is_ie ) {
+		Test.AnotherWay._g_no_record_msg="Input events recording and replaying is not available in internet explorer.";
+	}
+ 	if( Test.AnotherWay._g_no_record_msg!=null ) {
+		var no_record_p=document.getElementById( "record_not_supported" );
+		no_record_p.style.display="block";
+		no_record_p.appendChild( document.createTextNode( Test.AnotherWay._g_no_record_msg ) );
+	}
+
+	Test.AnotherWay._g_main_loaded=true;
+	if( Test.AnotherWay._g_run_on_main_load ) {
+		Test.AnotherWay._g_run_on_main_load=false;
+		Test.AnotherWay._run_pages_to_run();
+	}
+}
+// -->
+</script>
+<script type="text/javascript" src="xml_eq.js"></script>
+</head><body>
+
+<div id="col1">
+<div id="col1_header">Test pages:</div>
+<div id="scroller">
+<table id="testtable">
+</table>
+</div>
+<div id="run_buttons">
+<input type="button" value=" clear " id="clear_btn" />
+<input type="button" value=" run all " id="run_all" />
+<input type="button" value=" run selected " id="run_selected" />
+<input type="button" value=" unselect all " id="unselect_all" />
+</div>
+<input type="checkbox" id="dont_close_test_windows" /> do not close windows opened by tests
+<div id="error"></div>
+<div id="record_div">
+<p id="record_not_supported" style="display:none"></p>
+<p>Record mouse input for the page:</p>
+<p><input type="radio" name="record_choose" value="select" checked="checked" /> <select id="record_select"><option selected="selected">-- select a page: --</option></select></p>
+<p><input type="radio" name="record_choose" value="input" /> or enter page url: <input type="text" id="record_input" /></p>
+<p><input type="button" value=" record " id="record_start" /></p>
+</div>
+</div>
+
+<div id="col2">
+<div id="right_header">
+<span id="results_count">Results: <span id="total"></span></span>
+<span id="results_tab" class="active_tab" style="visibility:hidden">Results</span>
+<span id="debug_tab" class="inactive_tab" style="visibility:hidden">Debug</span>
+</div>
+<div id="right_frame">
+<div id="results"></div>
+<div id="debug"></div>
+</div>
+</div>
+
+<span style="display:none">
+<iframe name="list_iframe" onload="Test.AnotherWay._list_iframe_onload();"></iframe>
+<iframe name="test_iframe" onload="Test.AnotherWay._test_page_onload();"></iframe>
+
+<!-- record_control div is to be imported into other documents, so all its styles are inline -->
+-<div id="record_control" style="position:absolute;bottom:0;left:0;margin:0;padding:0.5em;width:22em;height:22em;border:1px solid;background:#ffd;font: normal normal 8pt sans-serif; color:#000; text-align: left">
+
+<p style="margin:0 0 0 0; padding:0">
+&nbsp;
+<span style="display:none;font-weight:bold;color:#408" id="record_indicator">
+recording. <span style="font-weight:normal">time: <span id="record_time"></span></span><span id="record_pause_indicator"> paused</span>
+</span>
+</p>
+
+<div id="record_cursor_over" style="margin:0;padding:2px;width:14em;height:1.1em;overflow:hidden;float:right;border:1px solid #777;background:#fff;font: normal normal 8pt sans-serif;position:relative;top:3px;color:#000;text-align:left;">&nbsp;</div>
+<p style="margin:2px 0 0 0; padding:0">
+cursor is over
+</p>
+
+<p style="margin:8px 0 0 0; padding:0;">
+ keyboard control: press
+ <span id="record_ctrl_key" style="border:1px solid #226;background:#adf;padding:0 0.5em">ctrl</span> -
+ <span id="record_shift_key" style="border:1px solid #226;background:#adf;padding:0 0.5em">shift</span> -
+</p>
+
+<p style="margin:4px 0 0 0; padding:0">
+<span id="record_s" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">s</span>
+<span id="record_on">to <b>start</b> recording</span>
+<span id="record_off" style="display:none">to <b>stop</b> recording</span>
+</p>
+
+<p style="margin:4px 0 0 0; padding:0">
+<span id="record_h" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">h</span>
+<span>to <b>hide/show</b> this window</span>
+</p>
+
+<p style="margin:4px 0 0 0; padding:0">
+<span id="record_m" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">m</span>
+<span id="record_include_mousemove">to <b> record</b> mousemove</span>
+<span id="record_omit_mousemove" style="display:none">to <b>omit</b> mousemove</span>
+</p>
+
+<p style="margin:4px 0 0 0; padding:0">
+<span id="record_p" style="border:1px solid #226;background:#aaa;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">p</span>
+<span id="record_pause_on">to <b> pause</b> recording</span>
+<span id="record_pause_off" style="display:none">to <b>continue</b> recording</span>
+</p>
+
+<p style="margin:4px 0 0 0; padding:0">
+<span id="record_c" style="border:1px solid #226;background:#aaa;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">c</span>
+<span>to add checkpoint</span>
+</p>
+
+<p style="margin:6px 0 0 0; padding:0">
+checkpoints:
+</p>
+<div id="record_checkpoints" style="position:relative;width:100%;height:6em;overflow:auto;font: normal normal 8pt sans-serif; color:#000; text-align: left">
+</div>
+</div>
+
+</span>
+</body></html>

Added: addins/timedpointtrack/trunk/theme/default/timedpointtrack.css
===================================================================
--- addins/timedpointtrack/trunk/theme/default/timedpointtrack.css	                        (rev 0)
+++ addins/timedpointtrack/trunk/theme/default/timedpointtrack.css	2010-11-29 08:56:27 UTC (rev 10921)
@@ -0,0 +1,9 @@
+div.olControlTimeDisplay {
+    bottom: 0em;
+    left: 3px;
+    display: block;
+    position: absolute;
+    font-family: Arial;
+    font-size: smaller;
+}
+



More information about the Commits mailing list