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