source: subversion/applications/editors/django/osmeditor/static/map.html @ 13700

Last change on this file since 13700 was 13700, checked in by crschmidt, 10 years ago

use hash-based permalinks so map state isn't lost across node/object loads.

File size: 16.3 KB
Line 
1<html xmlns="http://www.w3.org/1999/xhtml">
2  <head>
3    <title>Simple OSM Editor Map Viewer</title>
4    <script src="http://openlayers.org/api/OpenLayers.js"></script>
5        <script src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=euzuro-openlayers"></script>
6
7    <link rel="stylesheet" href="http://openlayers.org/api/theme/default/style.css" type="text/css" />
8    <link rel="stylesheet" href="/static/base.css" type="text/css" />
9
10    <style type="text/css">
11       #helpLink {
12        font-size: smaller;
13        position: absolute;
14        right: 25px;
15        bottom: 53px;
16        z-index: 10000;
17       }
18       #loginLink {
19        font-size: 1.3em;
20        position: absolute;
21        right: 25px;
22        top: 100px;
23        color: red;
24        z-index: 10000;
25        background-color: white;
26       }
27       #loginLink a {
28        color: red;
29       }
30       .permalink {
31        font-size: smaller;
32        position: absolute;
33        right: 1em;
34        bottom: 17px;
35        z-index: 10000;
36       }
37       .potlatchLink {
38        font-size: smaller;
39        position: absolute;
40        right: 7em;
41        bottom: 17px;
42        z-index: 10000;
43       }
44       .olControlPermalink {
45        bottom: 3px;
46       } 
47       .olControlAttribution {
48        bottom: 20px;
49       } 
50    </style> 
51    <script type="text/javascript">
52        var map, layer;
53        var OSMEditor = {};
54        OSMEditor.HashControl = OpenLayers.Class(OpenLayers.Control.Permalink, {
55            updateLink: function() {
56                var href = OpenLayers.Util.getParameterString(this.createParams());
57                document.location.hash= "m-"+href;
58                this.element.href = document.location.hash;
59            },
60    draw: function() {
61        OpenLayers.Control.prototype.draw.apply(this, arguments);
62         
63        if (!this.element) {
64            this.div.className = this.displayClass;
65            this.element = document.createElement("a");
66            this.element.innerHTML = OpenLayers.i18n("permalink");
67            this.element.href="";
68            this.div.appendChild(this.element);
69        }
70        this.map.events.on({
71            'moveend': this.updateLink,
72            'changelayer': this.updateLink,
73            'changebaselayer': this.updateLink,
74            scope: this
75        });
76       
77        // Make it so there is at least a link even though the map may not have
78        // moved yet.
79        this.updateLink();
80       
81        return this.div;
82    }
83        });
84        OSMEditor.HashParser = OpenLayers.Class(OpenLayers.Control.ArgParser, {
85            setMap: function(map) {
86                OpenLayers.Control.prototype.setMap.apply(this, arguments);
87                    var hstr = "?"+document.location.hash.substr(3, document.location.hash.length - 1);
88                    var args = OpenLayers.Util.getParameters(hstr);
89                    // Be careful to set layer first, to not trigger unnecessary layer loads
90                    if (args.layers) {
91                        this.layers = args.layers;
92   
93                        // when we add a new layer, set its visibility
94                        this.map.events.register('addlayer', this, 
95                                                 this.configureLayers);
96                        this.configureLayers();
97                    }
98                    if (args.lat && args.lon) {
99                        this.center = new OpenLayers.LonLat(parseFloat(args.lon),
100                                                            parseFloat(args.lat));
101                        if (args.zoom) {
102                            this.zoom = parseInt(args.zoom);
103                        }
104   
105                        // when we add a new baselayer to see when we can set the center
106                        this.map.events.register('changebaselayer', this, 
107                                                 this.setCenter);
108                        this.setCenter();
109                    }
110            }
111        });
112
113   
114        OSMEditor.CreatePOIClick = OpenLayers.Class(OpenLayers.Control, {               
115             title: 'Create POI',
116             initialize: function(options) {
117                 OpenLayers.Control.prototype.initialize.apply(
118                     this, arguments
119                 ); 
120                 this.handler = new OpenLayers.Handler.Click(
121                     this, {
122                         'dblclick': this.onClick,
123                     }, {
124                         'double': true,
125                         'stopDouble': true,
126                         'single': false
127                     }
128                 );
129             }, 
130
131             onClick: function(evt) {
132                 var xy = evt.xy;
133                 var f = new OpenLayers.Format.XML();
134                 var loc = map.getLonLatFromPixel(evt.xy);
135                 loc.transform(map.getProjectionObject(), map.displayProjection);
136                 var osm = f.createElementNS(null, "osm");
137                 osm.setAttribute("version", "0.5");
138                 var node = f.createElementNS(null, "node");
139                 node.setAttribute("lon", loc.lon);
140                 node.setAttribute("lat", loc.lat);
141                 osm.appendChild(node);
142                 var node = f.write(osm);
143                 var request = OpenLayers.Request.PUT({
144                     url: "/api/0.5/node/create",
145                     data: node,
146                     callback: this.handleResponse
147                 });           
148             },
149
150             handleResponse: function(req) {
151                if (req.status == 401) {
152                    alert("Login first!");
153                    $("loginA").style.display="inline";
154                } else {   
155                 var id = req.responseText;
156                 document.location = "/node/" + id;
157                } 
158             }
159        });     
160        OSMEditor.LoadDataClick = OpenLayers.Class(OpenLayers.Control, {               
161             title: 'Browse OSM Data by clicking',
162             initialize: function(options) {
163                 OpenLayers.Control.prototype.initialize.apply(
164                     this, arguments
165                 ); 
166                 this.handler = new OpenLayers.Handler.Click(
167                     this, {
168                         'click': this.onClick
169                     }
170                 );
171             }, 
172
173             onClick: function(evt) {
174                 if (map.getResolution() > 30) {
175                     alert("sorry, zoom in");
176                     return;
177                 }   
178                 var output = document.getElementById("data");
179                 var xy = evt.xy;
180                 var b = new OpenLayers.Bounds();
181                 b.extend(map.getLonLatFromPixel(new OpenLayers.Pixel(xy.x-30, xy.y-30)));
182                 b.extend(map.getLonLatFromPixel(new OpenLayers.Pixel(xy.x+30, xy.y+30)));
183                 this.lastLonLat = b.getCenterLonLat();
184                 if (this.selectFeature) {
185                     this.selectFeature.destroy();
186                 }   
187                 if (this.layers) {
188                     for (var i = 0; i <this.layers.length; i++) {
189                         this.layers[i].destroy();
190                     }
191                 }
192                 $("data").innerHTML = "";
193                 $("loading").innerHTML = "Loading...";
194                 var styleMap = new OpenLayers.StyleMap({'default': OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {strokeWidth: 5, cursor: 'pointer'})});
195
196                 this.layers = []
197                 this.layers.push(
198                     new OpenLayers.Layer.GML("OSM Data", 
199                         "/api/0.5/map?bbox="+b.clone().transform(map.getProjectionObject(), map.displayProjection).toBBOX(), 
200                         {format: OpenLayers.Format.OSM, styleMap: styleMap, projection: map.displayProjection}));
201                 
202                 var selectFeature = new OpenLayers.Control.SelectFeature(this.layers[0]);
203                 var click = this;
204                 for (var i = 0; i < this.layers.length; i++) {
205                     
206                     this.layers[i].events.on({
207                     'featureselected': 
208                         function(e) {
209                             var feature = e.feature;
210                             var type = "way"; 
211                             if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
212                                 type = "node";
213                             }   
214                             var s = "<a href='/" + type +"/" + feature.osm_id +"'>Edit "+ type + " " + feature.osm_id + "</a>";
215                             var tags = "<ul>"; 
216                             for (var key in feature.attributes) {
217                                 if (key.search(":") == -1) {
218                                     tags += "<li><b>" + key + "</b>: " + feature.attributes[key] + "</li>";
219                                 }
220                             }
221                             tags += "</ul>";
222                             document.getElementById("data").innerHTML = s + tags;
223                         },
224                     'featureunselected': function () {
225                         $("data").innerHTML = "";
226
227                     },
228                     "loadend": 
229                         function() { 
230                             $("loading").innerHTML = this.features.length + " loaded";
231                             if (this.features.length == 1) {
232                                 selectFeature.select(this.features[0]);
233                             } else {
234                                 var matches = [];
235                                 var point = new OpenLayers.Geometry.Point(click.lastLonLat.lon, click.lastLonLat.lat); 
236                                 for (var i = 0; i < this.features.length; i++) {
237                                      if (this.features[i].geometry.intersects(point)) {
238                                         matches.push(this.features[i]);
239                                      }
240                                 }
241                                 if (matches.length == 1) {
242                                     selectFeature.select(matches[0]);
243                                 }   
244                             }
245                                 
246                         }   
247                     });
248                 }   
249                 this.selectFeature = selectFeature;
250                 map.addControl(this.selectFeature);
251                 this.selectFeature.activate();
252                 
253                 map.addLayers(this.layers);
254             }
255
256         }); 
257        function onPopupClose(evt) {
258            selectControl.unselect(selectedFeature);
259        }
260        function onFeatureSelect(feature) {
261            selectedFeature = feature;
262            popup = new OpenLayers.Popup.FramedCloud("featurePopup", 
263                                     feature.geometry.getBounds().getCenterLonLat(),
264                                     null,
265                                     "<div style='font-size:.8em'>Feature: " + feature.attributes.osm_id +"<br />Area: " + feature.geometry.getArea()+"</div>",
266                                     null, true, onPopupClose);
267            feature.popup = popup;
268            map.addPopup(popup);
269        }
270        function onFeatureUnselect(feature) {
271            map.removePopup(feature.popup);
272            feature.popup.destroy();
273            feature.popup = null;
274        }   
275        function init(){
276            var options = {
277                projection: new OpenLayers.Projection("EPSG:900913"),
278                displayProjection: new OpenLayers.Projection("EPSG:4326"),
279                units: "m",
280                maxResolution: 156543.03392804062,
281                numZoomLevels: 19,
282                maxExtent: new OpenLayers.Bounds(-20037508.342787, -20037508.342788, 20037508.342789, 20037508.342789 ),
283                controls: [new OSMEditor.HashParser(), new OpenLayers.Control.PanZoomBar(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.Attribution()]
284            };
285
286            map = new OpenLayers.Map( 'map', options );
287            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
288                    "http://labs.metacarta.com/wms/vmap0",
289                    {layers: 'basic'} );
290            var mapnik = new OpenLayers.Layer.TMS(
291                "Mapnik (OpenStreetMap)",
292                  ["http://a.tile.openstreetmap.org/",
293                   "http://b.tile.openstreetmap.org/"],
294                {
295                    type: 'png', getURL: osm_getTileURL,
296                    attribution: '&copy; <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors',
297                    buffer: 0
298                }
299            );
300            var cyclemap = new OpenLayers.Layer.TMS(
301                "CycleMap (CloudMade)",
302                [
303                "http://a.andy.sandbox.cloudmade.com/tiles/cycle/",
304                "http://b.andy.sandbox.cloudmade.com/tiles/cycle/",
305                "http://c.andy.sandbox.cloudmade.com/tiles/cycle/"
306                ], 
307                {
308                    type: 'png', getURL: osm_getTileURL,
309                    attribution: '&copy; <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors',
310                    buffer: 0
311                }
312            );
313            var minutelyNoName = new OpenLayers.Layer.TMS(
314                "No Name (CloudMade)",
315                ["http://a.matt.sandbox.cloudmade.com/123/3/256/", 
316                 "http://b.matt.sandbox.cloudmade.com/123/3/256/", 
317                 "http://c.matt.sandbox.cloudmade.com/123/3/256/"
318                ],
319                {
320                    type: 'png', getURL: osm_getTileURL,
321                    attribution: '&copy; <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors',
322                    buffer: 0
323                }
324            );
325            var yahoo = new OpenLayers.Layer.Yahoo("Yahoo", {sphericalMercator: true, 'type': YAHOO_MAP_SAT, MAX_ZOOM_LEVEL: 17});
326
327
328            var panel = new OpenLayers.Control.Panel({displayClass: 'mainMapToolbar'});
329            var loadData = new OSMEditor.LoadDataClick({
330                'displayClass': 'loadData'
331            });
332            var vlayer = new OpenLayers.Layer.Vector("OSM Data");
333            map.addLayer(vlayer);
334            loadData.layers = [vlayer]; 
335            panel.addControls(loadData);
336            panel.addControls(new OSMEditor.CreatePOIClick({
337                'displayClass': 'createPoi'
338            }));
339            map.addControl(panel);
340            panel.activate();
341            panel.activateControl(panel.controls[0]);
342            map.addControl(new OSMEditor.HashControl());
343            map.addControl(new OpenLayers.Control.Permalink($("potlatchLinkHref"), "http://openstreetmap.org/edit.html", {displayClass: 'potlatchLink'}));
344            map.addLayers([mapnik, cyclemap, minutelyNoName, yahoo]);
345            map.addControl(new OpenLayers.Control.LayerSwitcher());
346            if (!map.getCenter()) { map.zoomToMaxExtent(); }
347        }
348        function osm_getTileURL(bounds) {
349            var res = this.map.getResolution();
350            var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
351            var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
352            var z = this.map.getZoom();
353            var limit = Math.pow(2, z);
354
355            if (y < 0 || y >= limit || x < 0 || x >= limit) {
356                return OpenLayers.Util.getImagesLocation() + "blank.gif";
357            } else {
358                x = ((x % limit) + limit) % limit;
359                var path = z + "/" + x + "/" + y + "." + this.type;
360                var url = this.url;
361                if (url instanceof Array) {
362                    url = this.selectUrl(path, url);
363                }
364                return url + path;
365            }
366        }
367
368    </script>
369  </head>
370
371  <body onload="init()">
372    <div id="map" style="width:99%; height:99%">
373        <div id="loginLink"><a id="loginA" href="/login/" target="_blank" style="display:none">Login</a></div>
374        <div id="helpLink"><a href="/help/" target="_blank">Help?</a></div>
375        <div id="data" style="position:absolute; left: 5px; bottom:5px; z-index:10000; background-color: white; padding: 5px"></div>
376        <div id="loading" style="position:absolute; right: 200px; top:5px; z-index:10000"></div>
377        <div class="potlatchLink"><a id="potlatchLinkHref">Edit (with Potlatch)</a></div>
378    </div>
379
380  </body>
381</html>
382
Note: See TracBrowser for help on using the repository browser.