1/* 2 * Copyright (c) 2008-2011 Mark C. Prins <mc.prins@gmail.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/** 18 * @fileoverview Javascript voor OpenLayers plugin. 19 * 20 * @requires {lib/OpenLayers.js} or other full openlayers build 21 * @author Mark C. Prins <mc.prins@gmail.com> 22 * 23 */ 24 25/** 26 * Openlayers selectcontrol. 27 * 28 * @type {OpenLayers.Control.SelectFeature} 29 * @private 30 */ 31var selectControl; 32/** 33 * Openlayers bounds used for managing the map extent. 34 * 35 * @type {OpenLayers.Bounds} 36 * @private 37 */ 38var extent; 39 40/** 41 * handle feature select event. 42 * 43 * @param {OpenLayers.Feature.Vector} 44 * the selected feature 45 */ 46function onFeatureSelect(feature) { 47 var selectedFeature = feature; 48 // 'this' is selectFeature control 49 var pPos = selectedFeature.geometry.getBounds().getCenterLonLat(); 50 // != OpenLayers.Geometry.Point 51 if (selectedFeature.geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { 52 try { 53 // for lines make the popup show at the cursor position 54 pPos = feature.layer.map 55 .getLonLatFromViewPortPx(this.handlers.feature.evt.xy); 56 } catch (anErr) { 57 console 58 .warn("unable to get event position; reverting to boundingbox center."); 59 pPos = selectedFeature.geometry.getBounds().getCenterLonLat(); 60 } 61 } 62 63 var pContent = ""; 64 if (feature.data.rowId != undefined) { 65 pContent += "<span style=''>" + feature.data.rowId + ": </span>"; 66 } 67 if (feature.data.name != undefined) { 68 pContent += "<div style=''>" + feature.data.name + "<br /></div>"; 69 } 70 if (feature.data.ele != undefined) { 71 pContent += "<div style=''>elevation: " + feature.data.ele 72 + "<br /></div>"; 73 } 74 if (feature.data.type != undefined) { 75 pContent += "<div style=''>" + feature.data.type + "<br /></div>"; 76 } 77 if (feature.data.time != undefined) { 78 pContent += "<div style=''>time: " + feature.data.time + "<br /></div>"; 79 } 80 if (feature.data.description != undefined) { 81 pContent += "<div style=''>" + feature.data.description + "</div>"; 82 } 83 84 if (pContent.length > 0) { 85 var popup = new OpenLayers.Popup.FramedCloud("olPopup", pPos, null, 86 pContent, null, true, function() { 87 selectControl.unselect(selectedFeature); 88 }); 89 feature.popup = popup; 90 feature.layer.map.addPopup(popup); 91 } 92} 93 94/** 95 * handle feature unselect event. remove & destroy the popup. 96 * 97 * @param {OpenLayers.Feature.Vector} 98 * the un-selected feature 99 */ 100function onFeatureUnselect(feature) { 101 if (feature.popup != null) { 102 feature.layer.map.removePopup(feature.popup); 103 feature.popup.destroy(); 104 feature.popup = null; 105 } 106} 107 108// TODO IE7 and lower don't have document.getElementsByClassName so we make one; 109// seems to conflict with openlayers prototypes? 110// Object.prototype.getElementsByClassName = document.getElementsByClassName = 111// document.getElementsByClassName 112// || function(className) { 113// className = className.replace(/\s+/g, ' ').replace( 114// /^\s|![A-Za-z0-9-_\s]|\s$/g, '').split(' '); 115// for ( var i = 0, elements = this.getElementsByTagName('*'), elementsLength = 116// elements.length, b = [], classNameLength = className.length, passed = true; i 117// < elementsLength; i++, passed = true) { 118// for ( var j = 0; j < classNameLength && passed; j++) { 119// passed = (new RegExp( 120// '(^|\\\s)' + className[j] + '(\\\s|$)', 'i')) 121// .test(elements[i].className); 122// } 123// if (passed) { 124// b.push(elements[i]); 125// } 126// } 127// return b; 128// }; 129 130/** init. */ 131function olInit() { 132 // hide the table with POI 133 // var tbls = getElementsByClass('olPOItable', document, 'table'); 134 var tbls = getElementsByClass('olPOItable', null, null); 135 // var tbls = getElementsByClassName('olPOItable'); 136 // console.log(tbls); 137 for (i = 0; i < tbls.length; i++) { 138 tbls[i].className = tbls[i].className + ' olPrintOnly'; 139 } 140} 141 142/** 143 * create the map based on the params given. 144 * 145 * @param {Object}mapOpts 146 * MapOptions hash {id:'olmap', lat:6710200, lon:506500, zoom:13, 147 * toolbar:1, statusbar:1, controls:1, poihoverstyle:1, baselyr:'', 148 * kmlfile:'', gpxfile:'', summary:''} 149 * @param {Array}OLmapPOI 150 * array with POI's [ {lat:6710300,lon:506000,txt:'instap 151 * punt',angle:180,opacity:.9,img:'', rowId:n},... ]); 152 * 153 */ 154function createMap(mapOpts, OLmapPOI) { 155 if (!olEnable) { 156 return; 157 } 158 OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3; 159 OpenLayers.Util.onImageLoadErrorColor = "transparent"; 160 // http://mapbox.com/documentation/adding-tiles-your-site/openlayers-themes 161 // OpenLayers.ImgPath = ''; 162 163 var extent = new OpenLayers.Bounds(); 164 165 var mOpts = { 166 projection : new OpenLayers.Projection("EPSG:900913"), 167 displayProjection : new OpenLayers.Projection("EPSG:4326"), 168 units : "m", 169 maxResolution : 156543.0339, 170 maxExtent : new OpenLayers.Bounds(-20037508.3392, -20037508.3392, 171 20037508.3392, 20037508.3392), 172 controls : [], 173 numZoomLevels : 19 174 }; 175 var m = new OpenLayers.Map(mapOpts.id, mOpts); 176 /* OSM maps */ 177 m.addLayer(new OpenLayers.Layer.OSM("OpenStreetMap"), { 178 transitionEffect : "resize" 179 }); 180 m.addLayer(new OpenLayers.Layer.OSM("t@h", 181 "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"), { 182 transitionEffect : "resize" 183 }); 184 m 185 .addLayer( 186 new OpenLayers.Layer.OSM("cycle map", 187 "http://andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png"), 188 { 189 transitionEffect : "resize" 190 }); 191 m 192 .addLayer(new OpenLayers.Layer.OSM( 193 "cloudmade map", 194 "http://tile.cloudmade.com/2f59745a6b525b4ebdb100891d5b6711/3/256/${z}/${x}/${y}.png", 195 { 196 transitionEffect : "resize" 197 })); 198 m.addLayer(new OpenLayers.Layer.OSM("hike and bike map", 199 "http://toolserver.org/tiles/hikebike/${z}/${x}/${y}.png", { 200 transitionEffect : "resize" 201 })); 202 /* open aerial map */ 203 /* 204 * turn this off; project is asleep: 205 * https://sourceforge.net/tracker/?func=detail&aid=2897327&group_id=239475&atid=1110186 206 * m.addLayer(new OpenLayers.Layer.XYZ("OpenAerialMap", 207 * "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/${z}/${x}/${y}.jpg", 208 * {name: "OpenStreetMap", attribution: "Data CC-By by <a 209 * href='http://www.openaerialmap.org/licensing/'>OpenAerialMap</a>", 210 * sphericalMercator: true, transitionEffect: "resize"} )); 211 */ 212 213 /* controle of google/yahoo/ve api's beschikbaar zijn.. */ 214 if (gEnable) { 215 try { 216 m.addLayer(new OpenLayers.Layer.Google("google relief", { 217 type : G_PHYSICAL_MAP, 218 'sphericalMercator' : true, 219 transitionEffect : "resize" 220 })); 221 m.addLayer(new OpenLayers.Layer.Google("google sat", { 222 type : G_SATELLITE_MAP, 223 'sphericalMercator' : true, 224 transitionEffect : "resize" 225 })); 226 m.addLayer(new OpenLayers.Layer.Google("google hybrid", { 227 type : G_HYBRID_MAP, 228 'sphericalMercator' : true, 229 transitionEffect : "resize" 230 })); 231 m.addLayer(new OpenLayers.Layer.Google("google normal", { 232 type : G_NORMAL_MAP, 233 'sphericalMercator' : true, 234 transitionEffect : "resize" 235 })); 236 } catch (ol_err1) { 237 } 238 } 239 240 if (yEnable) { 241 try { 242 m.addLayer(new OpenLayers.Layer.Yahoo("yahoo", { 243 'type' : YAHOO_MAP_HYB, 244 'sphericalMercator' : true, 245 transitionEffect : resize 246 })); 247 } catch (ol_err2) { 248 } 249 } 250 251 if (veEnable) { 252 try { 253 m.addLayer(new OpenLayers.Layer.VirtualEarth("ve", { 254 'type' : VEMapStyle.Hybrid, 255 'sphericalMercator' : true, 256 transitionEffect : resize 257 })); 258 } catch (ol_err3) { 259 } 260 } 261 m.setCenter(new OpenLayers.LonLat(mapOpts.lon, mapOpts.lat).transform( 262 m.displayProjection, m.projection), mapOpts.zoom); 263 extent.extend(m.getExtent()); 264 265 m.addControl(new OpenLayers.Control.KeyboardDefaults()); 266 m.addControl(new OpenLayers.Control.Navigation()); 267 if (mapOpts.controls === 1) { 268 /* add base controls to map */ 269 m.addControl(new OpenLayers.Control.LayerSwitcher()); 270 m.addControl(new OpenLayers.Control.ScaleLine({ 271 geodesic : true 272 })); 273 m.addControl(new OpenLayers.Control.PanZoomBar()); 274 m.addControl(new OpenLayers.Control.Graticule({ 275 visible : false 276 })); 277 // TODO optioneel overzichts kaart toevoegen 278 // var overViewOpts = {layers: [wms.clone()],size: new 279 // OpenLayers.Size(120,120),projection: new 280 // OpenLayers.Projection("EPSG:900913"),opacity: 0.0,mapOptions: { 281 // /* Available resolutions are: [156543.03390000001, 282 // 78271.516950000005, 283 // 39135.758475000002, 19567.879237500001, 9783.9396187500006, 284 // 4891.9698093750003, 2445.9849046875001, 1222.9924523437501, 285 // 611.49622617187504, 305.74811308593752, 152.87405654296876, 286 // 76.43702827148438, 38.21851413574219, 19.109257067871095, 287 // 9.5546285339355475, 288 // 4.7773142669677737, 2.3886571334838869, 1.1943285667419434, 289 // 0.59716428337097172, 0.29858214168548586]*/ 290 // maxResolution: 78271.51695,maxExtent: new 291 // OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34), 292 // /* 293 // minExtent: new OpenLayers.Bounds(1000,400000,400000,515000),*/ 294 // numZoomLevels: 5},'div':OpenLayers.Util.getElement('overview')}; 295 // map.addControl(new OpenLayers.Control.OverviewMap(overViewOpts)); 296 } 297 298 if (mapOpts.statusbar === 1) { 299 // statusbar control: permalink 300 m.addControl(new OpenLayers.Control.Permalink(mapOpts.id 301 + '-statusbar-link-ref')); 302 // statusbar control: mouse pos. 303 // TODO kijken naar afronding met aNumber.toFixed(0) 304 m.addControl(new OpenLayers.Control.MousePosition({ 305 'div' : OpenLayers.Util.getElement(mapOpts.id 306 + '-statusbar-mouseposition') 307 })); 308 // statusbar control: scale 309 m.addControl(new OpenLayers.Control.Scale(mapOpts.id 310 + '-statusbar-scale')); 311 // statusbar control: attribution 312 m.addControl(new OpenLayers.Control.Attribution({ 313 'div' : OpenLayers.Util.getElement(mapOpts.id + '-statusbar-text') 314 })); 315 // statusbar control: projection 316 OpenLayers.Util.getElement(mapOpts.id + '-statusbar-projection').innerHTML = m.displayProjection; 317 } else { 318 OpenLayers.Util.getElement(mapOpts.id + '-olStatusBar').display = 'none'; 319 } 320 321 if (mapOpts.toolbar === 1) { 322 // buttons + panel 323 var zoomin = new OpenLayers.Control.ZoomBox({ 324 title : "Zoom in" 325 }); 326 var zoomout = new OpenLayers.Control.ZoomBox({ 327 out : true, 328 title : "Zoom uit", 329 displayClass : "olControlZoomOut" 330 }); 331 var pan = new OpenLayers.Control.DragPan({ 332 title : "Verschuif" 333 }); 334 // icon_query.png 335 var nav = new OpenLayers.Control.NavigationHistory(); 336 m.addControl(nav); 337 var panel = new OpenLayers.Control.Panel({ 338 defaultControl : zoomin, 339 displayClass : "olToolbar", 340 "div" : OpenLayers.Util.getElement(mapOpts.id + "-olToolbar") 341 }); 342 panel.addControls([ zoomin, zoomout, pan ]); 343 panel.addControls([ nav.next, nav.previous ]); 344 m.addControl(panel); 345 } else { 346 OpenLayers.Util.getElement(mapOpts.id + '-olToolbar').display = 'none'; 347 } 348 349 // add overlays 350 m.addLayer(new OpenLayers.Layer.OSM("Hillshade", 351 "http://toolserver.org/~cmarqu/hill/${z}/${x}/${y}.png", { 352 transitionEffect : "resize", 353 isBaseLayer : false, 354 transparent : true, 355 visibility : false 356 })); 357 358 var DocBase = DOKU_BASE; 359 if (OLmapPOI.length > 0) { 360 var markers = new OpenLayers.Layer.Vector( 361 "POI", 362 { 363 styleMap : new OpenLayers.StyleMap( 364 { 365 "default" : { 366 externalGraphic : "${img}", 367 graphicHeight : 16, 368 graphicWidth : 16, 369 graphicXOffset : 0, 370 graphicYOffset : -8, 371 graphicOpacity : "${opacity}", 372 rotation : "${angle}", 373 backgroundGraphic : DocBase 374 + "lib/plugins/openlayersmap/icons/marker_shadow.png", 375 backgroundXOffset : 0, 376 backgroundYOffset : -4, 377 backgroundRotation : "${angle}", 378 pointRadius : 10, 379 fontSize : "12px", 380 // fontFamily: "Courier New, monospace", 381 labelXOffset : 5, 382 labelYOffset : 5, 383 labelAlign : "lb", 384 label : "${label}" 385 }, 386 "select" : { 387 cursor : "crosshair", 388 externalGraphic : DocBase 389 + "lib/plugins/openlayersmap/icons/marker-red.png", 390 graphicHeight : 16, 391 graphicWidth : 16, 392 graphicXOffset : 0, 393 graphicYOffset : -8, 394 graphicOpacity : 1.0, 395 rotation : "${angle}" 396 } 397 }), 398 isBaseLayer : false, 399 rendererOptions : { 400 yOrdering : true 401 } 402 }); 403 404 m.addLayer(markers); 405 var features = []; 406 var lonLat; 407 for ( var j = 0; j < OLmapPOI.length; j++) { 408 var feat = new OpenLayers.Feature.Vector( 409 new OpenLayers.Geometry.Point(OLmapPOI[j].lon, 410 OLmapPOI[j].lat).transform(m.displayProjection, 411 m.projection), { 412 angle : OLmapPOI[j].angle, 413 opacity : OLmapPOI[j].opacity, 414 img : DocBase + "lib/plugins/openlayersmap/icons/" 415 + OLmapPOI[j].img, 416 label : OLmapPOI[j].rowId 417 }); 418 feat.data = { 419 name : OLmapPOI[j].txt, 420 rowId : OLmapPOI[j].rowId 421 }; 422 features.push(feat); 423 } 424 markers.addFeatures(features); 425 extent.extend(markers.getDataExtent()); 426 m.zoomToExtent(extent); 427 } 428 429 /* GPX layer */ 430 if (mapOpts.gpxfile.length > 0) { 431 var layerGPX = new OpenLayers.Layer.GML("GPS route", DocBase 432 + "lib/exe/fetch.php?media=" + mapOpts.gpxfile, { 433 format : OpenLayers.Format.GPX, 434 formatOptions : { 435 extractWaypoints : true, 436 extractTracks : true, 437 extractStyles : true, 438 extractAttributes : true, 439 handleHeight : true, 440 maxDepth : 3 441 }, 442 style : { 443 strokeColor : "#0000FF", 444 strokeWidth : 3, 445 strokeOpacity : 0.7, 446 pointRadius : 4, 447 fillColor : "#0099FF", 448 fillOpacity : 0.7 449 /* 450 * , label:"${name}" 451 */}, 452 projection : new OpenLayers.Projection("EPSG:4326") 453 }); 454 m.addLayer(layerGPX); 455 layerGPX.events.register('loadend', m, function() { 456 extent.extend(layerGPX.getDataExtent()); 457 m.zoomToExtent(extent); 458 }); 459 460 } 461 462 /* KML layer */ 463 if (mapOpts.kmlfile.length > 0) { 464 var layerKML = new OpenLayers.Layer.GML("KML file", DocBase 465 + "lib/exe/fetch.php?media=" + mapOpts.kmlfile, { 466 format : OpenLayers.Format.KML, 467 formatOptions : { 468 extractStyles : true, 469 extractAttributes : true, 470 maxDepth : 3 471 }, 472 style : { 473 label : "${name}" 474 }, 475 projection : new OpenLayers.Projection("EPSG:4326") 476 }); 477 m.addLayer(layerKML); 478 layerKML.events.register('loadend', m, function() { 479 extent.extend(layerKML.getDataExtent()); 480 m.zoomToExtent(extent); 481 }); 482 } 483 484 // selectcontrol for layers 485 if ((m.getLayersByClass('OpenLayers.Layer.GML').length > 0) 486 || m.getLayersByClass('OpenLayers.Layer.Vector').length > 0) { 487 selectControl = new OpenLayers.Control.SelectFeature((m 488 .getLayersByClass('OpenLayers.Layer.Vector')).concat(m 489 .getLayersByClass('OpenLayers.Layer.GML')), { 490 multiple : true, 491 hover : mapOpts.poihoverstyle, 492 onSelect : onFeatureSelect, 493 onUnselect : onFeatureUnselect 494 }); 495 m.addControl(selectControl); 496 selectControl.activate(); 497 } 498 499 // change/set alternative baselyr 500 try { 501 m.setBaseLayer(m.getLayersByName(mapOpts.baselyr)[0]); 502 } catch (ol_err4) { 503 m.setBaseLayer(m.layers[0]); 504 } 505 return m; 506} 507 508/** 509 * ol api flag. 510 * 511 * @type {Boolean} 512 */ 513var olEnable = false; 514/** 515 * google map api flag. 516 * 517 * @type {Boolean} 518 */ 519var gEnable = false; 520/** 521 * virtual earth map api flag. 522 * 523 * @type {Boolean} 524 */ 525var veEnable = false; 526/** 527 * yahoo map api flag. 528 * 529 * @type {Boolean} 530 */ 531var yEnable = false; 532 533/* register olInit to run with onload event. */ 534addInitEvent(olInit); 535