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 */ 38extent; 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('olPOItableSpan', null, null); 134 for (i = 0; i < tbls.length; i++) { 135 // tbls[i].style.display = 'none'; 136 tbls[i].className += ' olPrintOnly'; 137 } 138 139 // hide the static map image 140 var statImgs = getElementsByClass('olStaticMap', null, null); 141 for (i = 0; i < statImgs.length; i++) { 142 // statImgs[i].style.display = 'none'; 143 statImgs[i].className += ' olPrintOnly'; 144 } 145 146 // show the dynamic map 147 var dynMaps = getElementsByClass('olContainer', null, null); 148 for (i = 0; i < dynMaps.length; i++) { 149 // dynMaps[i].style.display = 'inline'; 150 dynMaps[i].className += ' olWebOnly'; 151 } 152} 153 154/** 155 * create the map based on the params given. 156 * 157 * @param {Object}mapOpts 158 * MapOptions hash {id:'olmap', lat:6710200, lon:506500, zoom:13, 159 * toolbar:1, statusbar:1, controls:1, poihoverstyle:1, baselyr:'', 160 * kmlfile:'', gpxfile:'', summary:''} 161 * @param {Array}OLmapPOI 162 * array with POI's [ {lat:6710300,lon:506000,txt:'instap 163 * punt',angle:180,opacity:.9,img:'', rowId:n},... ]); 164 * 165 */ 166function createMap(mapOpts, OLmapPOI) { 167 if (!olEnable) { 168 return; 169 } 170 OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3; 171 OpenLayers.Util.onImageLoadErrorColor = "transparent"; 172 // http://mapbox.com/documentation/adding-tiles-your-site/openlayers-themes 173 // OpenLayers.ImgPath = ''; 174 175 /** dynamic map extent. */ 176 var extent = new OpenLayers.Bounds(), 177 /** map options. */ 178 mOpts = { 179 projection : new OpenLayers.Projection("EPSG:900913"), 180 displayProjection : new OpenLayers.Projection("EPSG:4326"), 181 units : "m", 182 maxResolution : 156543.0339, 183 maxExtent : new OpenLayers.Bounds(-20037508.3392, -20037508.3392, 184 20037508.3392, 20037508.3392), 185 controls : [], 186 numZoomLevels : 19 187 }, 188 /** map. */ 189 m = new OpenLayers.Map(mapOpts.id, mOpts); 190 191 /* add OSM map layers */ 192 m.addLayer(new OpenLayers.Layer.OSM("OpenStreetMap"), { 193 transitionEffect : "resize" 194 }); 195 m.addLayer(new OpenLayers.Layer.OSM("t@h", 196 "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"), { 197 transitionEffect : "resize" 198 }); 199 m 200 .addLayer( 201 new OpenLayers.Layer.OSM("cycle map", 202 "http://andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png"), 203 { 204 transitionEffect : "resize" 205 }); 206 m 207 .addLayer(new OpenLayers.Layer.OSM( 208 "cloudmade map", 209 "http://tile.cloudmade.com/2f59745a6b525b4ebdb100891d5b6711/3/256/${z}/${x}/${y}.png", 210 { 211 transitionEffect : "resize" 212 })); 213 m.addLayer(new OpenLayers.Layer.OSM("hike and bike map", 214 "http://toolserver.org/tiles/hikebike/${z}/${x}/${y}.png", { 215 transitionEffect : "resize" 216 })); 217/* add MapQuest map layers*/ 218 if (mqEnable) { 219 m 220 .addLayer(new OpenLayers.Layer.OSM( 221 "MapQuest road", 222 [ 223 "http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png", 224 "http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png", 225 "http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png", 226 "http://otile4.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png" ], 227 { 228 transitionEffect : "resize", 229 attribution : 'Data CC-By-SA by <a href="http://openstreetmap.org/" target="_blank">OpenStreetMap</a>' 230 + ' Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">' 231 })); 232 m 233 .addLayer(new OpenLayers.Layer.OSM( 234 "MapQuest aerial", 235 [ 236 "http://oatile1.mqcdn.com/naip/${z}/${x}/${y}.jpg", 237 "http://oatile2.mqcdn.com/naip/${z}/${x}/${y}.jpg", 238 "http://oatile3.mqcdn.com/naip/${z}/${x}/${y}.jpg", 239 "http://oatile4.mqcdn.com/naip/${z}/${x}/${y}.jpg" ], 240 { 241 transitionEffect : "resize", 242 attribution : 'Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">' 243 })); 244 } 245 246 /* open aerial map layers*/ 247 /* 248 * turn this off; project is asleep: 249 * https://sourceforge.net/tracker/?func=detail&aid=2897327&group_id=239475&atid=1110186 250 * m.addLayer(new OpenLayers.Layer.XYZ("OpenAerialMap", 251 * "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/${z}/${x}/${y}.jpg", 252 * {name: "OpenStreetMap", attribution: "Data CC-By by <a 253 * href='http://www.openaerialmap.org/licensing/'>OpenAerialMap</a>", 254 * sphericalMercator: true, transitionEffect: "resize"} )); 255 */ 256 257 /* controle of google/yahoo/ve api's beschikbaar zijn.. */ 258 if (gEnable) { 259 try { 260 m.addLayer(new OpenLayers.Layer.Google("google relief", { 261 type : G_PHYSICAL_MAP, 262 'sphericalMercator' : true, 263 transitionEffect : "resize" 264 })); 265 m.addLayer(new OpenLayers.Layer.Google("google sat", { 266 type : G_SATELLITE_MAP, 267 'sphericalMercator' : true, 268 transitionEffect : "resize" 269 })); 270 m.addLayer(new OpenLayers.Layer.Google("google hybrid", { 271 type : G_HYBRID_MAP, 272 'sphericalMercator' : true, 273 transitionEffect : "resize" 274 })); 275 m.addLayer(new OpenLayers.Layer.Google("google normal", { 276 type : G_NORMAL_MAP, 277 'sphericalMercator' : true, 278 transitionEffect : "resize" 279 })); 280 } catch (ol_err1) { 281 } 282 } 283 284// if (yEnable) { 285// try { 286// m.addLayer(new OpenLayers.Layer.Yahoo("yahoo", { 287// 'type' : YAHOO_MAP_HYB, 288// 'sphericalMercator' : true, 289// transitionEffect : resize 290// })); 291// } catch (ol_err2) { 292// } 293// } 294 295 if (veEnable) { 296 try { 297 m.addLayer(new OpenLayers.Layer.VirtualEarth("ve", { 298 'type' : VEMapStyle.Hybrid, 299 'sphericalMercator' : true, 300 transitionEffect : resize 301 })); 302 } catch (ol_err3) { 303 } 304 } 305 m.setCenter(new OpenLayers.LonLat(mapOpts.lon, mapOpts.lat).transform( 306 m.displayProjection, m.projection), mapOpts.zoom); 307 extent.extend(m.getExtent()); 308 309 m.addControl(new OpenLayers.Control.KeyboardDefaults()); 310 m.addControl(new OpenLayers.Control.Navigation()); 311 if (mapOpts.controls === 1) { 312 /* add base controls to map */ 313 m.addControl(new OpenLayers.Control.LayerSwitcher()); 314 m.addControl(new OpenLayers.Control.ScaleLine({ 315 geodesic : true 316 })); 317 m.addControl(new OpenLayers.Control.PanZoomBar()); 318 m.addControl(new OpenLayers.Control.Graticule({ 319 visible : false 320 })); 321 // TODO optioneel overzichts kaart toevoegen 322 // var overViewOpts = {layers: [wms.clone()],size: new 323 // OpenLayers.Size(120,120),projection: new 324 // OpenLayers.Projection("EPSG:900913"),opacity: 0.0,mapOptions: { 325 // /* Available resolutions are: [156543.03390000001, 326 // 78271.516950000005, 327 // 39135.758475000002, 19567.879237500001, 9783.9396187500006, 328 // 4891.9698093750003, 2445.9849046875001, 1222.9924523437501, 329 // 611.49622617187504, 305.74811308593752, 152.87405654296876, 330 // 76.43702827148438, 38.21851413574219, 19.109257067871095, 331 // 9.5546285339355475, 332 // 4.7773142669677737, 2.3886571334838869, 1.1943285667419434, 333 // 0.59716428337097172, 0.29858214168548586]*/ 334 // maxResolution: 78271.51695,maxExtent: new 335 // OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34), 336 // /* 337 // minExtent: new OpenLayers.Bounds(1000,400000,400000,515000),*/ 338 // numZoomLevels: 5},'div':OpenLayers.Util.getElement('overview')}; 339 // map.addControl(new OpenLayers.Control.OverviewMap(overViewOpts)); 340 } 341 342 if (mapOpts.statusbar === 1) { 343 // statusbar control: permalink 344 m.addControl(new OpenLayers.Control.Permalink(mapOpts.id 345 + '-statusbar-link-ref')); 346 // statusbar control: mouse pos. 347 // TODO kijken naar afronding met aNumber.toFixed(0) 348 m.addControl(new OpenLayers.Control.MousePosition({ 349 'div' : OpenLayers.Util.getElement(mapOpts.id 350 + '-statusbar-mouseposition') 351 })); 352 // statusbar control: scale 353 m.addControl(new OpenLayers.Control.Scale(mapOpts.id 354 + '-statusbar-scale')); 355 // statusbar control: attribution 356 m.addControl(new OpenLayers.Control.Attribution({ 357 'div' : OpenLayers.Util.getElement(mapOpts.id + '-statusbar-text') 358 })); 359 // statusbar control: projection 360 OpenLayers.Util.getElement(mapOpts.id + '-statusbar-projection').innerHTML = m.displayProjection; 361 } else { 362 OpenLayers.Util.getElement(mapOpts.id + '-olStatusBar').display = 'none'; 363 } 364 365 if (mapOpts.toolbar === 1) { 366 // buttons + panel 367 var zoomin = new OpenLayers.Control.ZoomBox({ 368 title : "Zoom in" 369 }); 370 var zoomout = new OpenLayers.Control.ZoomBox({ 371 out : true, 372 title : "Zoom uit", 373 displayClass : "olControlZoomOut" 374 }); 375 var pan = new OpenLayers.Control.DragPan({ 376 title : "Verschuif" 377 }); 378 // icon_query.png 379 var nav = new OpenLayers.Control.NavigationHistory(); 380 m.addControl(nav); 381 var panel = new OpenLayers.Control.Panel({ 382 defaultControl : zoomin, 383 displayClass : "olToolbar", 384 "div" : OpenLayers.Util.getElement(mapOpts.id + "-olToolbar") 385 }); 386 panel.addControls([ zoomin, zoomout, pan ]); 387 panel.addControls([ nav.next, nav.previous ]); 388 m.addControl(panel); 389 } else { 390 OpenLayers.Util.getElement(mapOpts.id + '-olToolbar').display = 'none'; 391 } 392 393 // add overlays 394 m.addLayer(new OpenLayers.Layer.OSM("Hillshade", 395 "http://toolserver.org/~cmarqu/hill/${z}/${x}/${y}.png", { 396 transitionEffect : "resize", 397 isBaseLayer : false, 398 transparent : true, 399 visibility : false 400 })); 401 402 var DocBase = DOKU_BASE; 403 if (OLmapPOI.length > 0) { 404 var markers = new OpenLayers.Layer.Vector( 405 "POI", 406 { 407 styleMap : new OpenLayers.StyleMap( 408 { 409 "default" : { 410 externalGraphic : "${img}", 411 graphicHeight : 16, 412 graphicWidth : 16, 413 graphicXOffset : 0, 414 graphicYOffset : -8, 415 graphicOpacity : "${opacity}", 416 rotation : "${angle}", 417 backgroundGraphic : DocBase 418 + "lib/plugins/openlayersmap/icons/marker_shadow.png", 419 backgroundXOffset : 0, 420 backgroundYOffset : -4, 421 backgroundRotation : "${angle}", 422 pointRadius : 10, 423 labelXOffset : 8, 424 labelYOffset : 8, 425 labelAlign : "lb", 426 label : "${label}", 427 // fontColor : "", 428 fontFamily : "monospace", 429 fontSize : "12px", 430 fontWeight : "bold" 431 }, 432 "select" : { 433 cursor : "crosshair", 434 externalGraphic : DocBase 435 + "lib/plugins/openlayersmap/icons/marker-red.png", 436 graphicHeight : 16, 437 graphicWidth : 16, 438 graphicXOffset : 0, 439 graphicYOffset : -8, 440 graphicOpacity : 1.0, 441 rotation : "${angle}" 442 } 443 }), 444 isBaseLayer : false, 445 rendererOptions : { 446 yOrdering : true 447 } 448 }); 449 450 m.addLayer(markers); 451 var features = []; 452 var lonLat; 453 for ( var j = 0; j < OLmapPOI.length; j++) { 454 var feat = new OpenLayers.Feature.Vector( 455 new OpenLayers.Geometry.Point(OLmapPOI[j].lon, 456 OLmapPOI[j].lat).transform(m.displayProjection, 457 m.projection), { 458 angle : OLmapPOI[j].angle, 459 opacity : OLmapPOI[j].opacity, 460 img : DocBase + "lib/plugins/openlayersmap/icons/" 461 + OLmapPOI[j].img, 462 label : OLmapPOI[j].rowId 463 }); 464 feat.data = { 465 name : OLmapPOI[j].txt, 466 rowId : OLmapPOI[j].rowId 467 }; 468 features.push(feat); 469 } 470 markers.addFeatures(features); 471 extent.extend(markers.getDataExtent()); 472 m.zoomToExtent(extent); 473 } 474 475 /* GPX layer */ 476 if (mapOpts.gpxfile.length > 0) { 477 var layerGPX = new OpenLayers.Layer.GML("GPS route", DocBase 478 + "lib/exe/fetch.php?media=" + mapOpts.gpxfile, { 479 format : OpenLayers.Format.GPX, 480 formatOptions : { 481 extractWaypoints : true, 482 extractTracks : true, 483 extractStyles : true, 484 extractAttributes : true, 485 handleHeight : true, 486 maxDepth : 3 487 }, 488 style : { 489 strokeColor : "#0000FF", 490 strokeWidth : 3, 491 strokeOpacity : 0.7, 492 pointRadius : 4, 493 fillColor : "#0099FF", 494 fillOpacity : 0.7 495 /* 496 * , label:"${name}" 497 */}, 498 projection : new OpenLayers.Projection("EPSG:4326") 499 }); 500 m.addLayer(layerGPX); 501 layerGPX.events.register('loadend', m, function() { 502 extent.extend(layerGPX.getDataExtent()); 503 m.zoomToExtent(extent); 504 }); 505 506 } 507 508 /* KML layer */ 509 if (mapOpts.kmlfile.length > 0) { 510 var layerKML = new OpenLayers.Layer.GML("KML file", DocBase 511 + "lib/exe/fetch.php?media=" + mapOpts.kmlfile, { 512 format : OpenLayers.Format.KML, 513 formatOptions : { 514 extractStyles : true, 515 extractAttributes : true, 516 maxDepth : 3 517 }, 518 style : { 519 label : "${name}" 520 }, 521 projection : new OpenLayers.Projection("EPSG:4326") 522 }); 523 m.addLayer(layerKML); 524 layerKML.events.register('loadend', m, function() { 525 extent.extend(layerKML.getDataExtent()); 526 m.zoomToExtent(extent); 527 }); 528 } 529 530 // selectcontrol for layers 531 if ((m.getLayersByClass('OpenLayers.Layer.GML').length > 0) 532 || m.getLayersByClass('OpenLayers.Layer.Vector').length > 0) { 533 selectControl = new OpenLayers.Control.SelectFeature((m 534 .getLayersByClass('OpenLayers.Layer.Vector')).concat(m 535 .getLayersByClass('OpenLayers.Layer.GML')), { 536 multiple : true, 537 hover : mapOpts.poihoverstyle, 538 onSelect : onFeatureSelect, 539 onUnselect : onFeatureUnselect 540 }); 541 m.addControl(selectControl); 542 selectControl.activate(); 543 } 544 545 // change/set alternative baselyr 546 try { 547 m.setBaseLayer(m.getLayersByName(mapOpts.baselyr)[0]); 548 } catch (ol_err4) { 549 m.setBaseLayer(m.layers[0]); 550 } 551 return m; 552} 553 554/** 555 * ol api flag. 556 * 557 * @type {Boolean} 558 */ 559var olEnable = false, 560/** 561 * MapQuest tiles flag. 562 * 563 * @type {Boolean} 564 */ 565mqEnable = false, 566/** 567 * google map api flag. 568 * 569 * @type {Boolean} 570 */ 571gEnable = false, 572/** 573 * virtual earth map api flag. 574 * 575 * @type {Boolean} 576 */ 577veEnable = false; 578/** 579 * yahoo map api flag. 580 * 581 * @type {Boolean} 582 */ 583//yEnable = false; 584 585/* register olInit to run with onload event. */ 586addInitEvent(olInit); 587