xref: /plugin/openlayersmap/script.js (revision ef819edba6cfdafa1bd5f353b47beba21d677025)
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