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