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