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