xref: /plugin/openlayersmap/script.js (revision 45c50327270724a4b1bef398d9485bdb3d46debb)
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.description != undefined) {
65		pContent += "<div style=''>" + feature.data.id + ": </div>";
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; seems to conflict with openlayers prototypes?
109// Object.prototype.getElementsByClassName = document.getElementsByClassName =
110// document.getElementsByClassName
111// || function(className) {
112// className = className.replace(/\s+/g, ' ').replace(
113// /^\s|![A-Za-z0-9-_\s]|\s$/g, '').split(' ');
114// for ( var i = 0, elements = this.getElementsByTagName('*'), elementsLength =
115// elements.length, b = [], classNameLength = className.length, passed = true; i
116// < elementsLength; i++, passed = true) {
117// for ( var j = 0; j < classNameLength && passed; j++) {
118// passed = (new RegExp(
119// '(^|\\\s)' + className[j] + '(\\\s|$)', 'i'))
120// .test(elements[i].className);
121// }
122// if (passed) {
123// b.push(elements[i]);
124// }
125// }
126// return b;
127// };
128
129/** init. */
130function olInit() {
131	// hide the table with POI
132	// var tbls = getElementsByClass('olPOItable', document, 'table');
133	var tbls = getElementsByClass('olPOItable', null, null);
134	// var tbls = getElementsByClassName('olPOItable');
135	// console.log(tbls);
136	for (i = 0; i < tbls.length; i++) {
137		tbls[i].className = 'olPOItable olPrintOnly';
138	}
139}
140
141/**
142 * create the map based on the params given.
143 *
144 * @param {Object}mapOpts
145 *            MapOptions hash {id:'olmap', lat:6710200, lon:506500, zoom:13,
146 *            toolbar:1, statusbar:1, controls:1, poihoverstyle:1, baselyr:'',
147 *            kmlfile:'', gpxfile:'', summary:''}
148 * @param {Array}OLmapPOI
149 *            array with POI's [ {lat:6710300,lon:506000,txt:'instap
150 *            punt',angle:180,opacity:.9,img:'', rowId:n},... ]);
151 *
152 */
153function createMap(mapOpts, OLmapPOI) {
154	if (!olEnable) {
155		return;
156	}
157	OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
158	OpenLayers.Util.onImageLoadErrorColor = "transparent";
159	// http://mapbox.com/documentation/adding-tiles-your-site/openlayers-themes
160	// OpenLayers.ImgPath = '';
161
162	var extent = new OpenLayers.Bounds();
163
164	var mOpts = {
165		projection : new OpenLayers.Projection("EPSG:900913"),
166		displayProjection : new OpenLayers.Projection("EPSG:4326"),
167		units : "m",
168		maxResolution : 156543.0339,
169		maxExtent : new OpenLayers.Bounds(-20037508.3392, -20037508.3392,
170				20037508.3392, 20037508.3392),
171		controls : [],
172		numZoomLevels : 19
173	};
174	var m = new OpenLayers.Map(mapOpts.id, mOpts);
175	/* OSM maps */
176	m.addLayer(new OpenLayers.Layer.OSM("OpenStreetMap"), {
177		transitionEffect : "resize"
178	});
179	m.addLayer(new OpenLayers.Layer.OSM("t@h",
180			"http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"), {
181		transitionEffect : "resize"
182	});
183	m
184			.addLayer(
185					new OpenLayers.Layer.OSM("cycle map",
186							"http://andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png"),
187					{
188						transitionEffect : "resize"
189					});
190	m
191			.addLayer(new OpenLayers.Layer.OSM(
192					"cloudmade map",
193					"http://tile.cloudmade.com/2f59745a6b525b4ebdb100891d5b6711/3/256/${z}/${x}/${y}.png",
194					{
195						transitionEffect : "resize"
196					}));
197	m.addLayer(new OpenLayers.Layer.OSM("hike and bike map",
198			"http://toolserver.org/tiles/hikebike/${z}/${x}/${y}.png", {
199				transitionEffect : "resize"
200			}));
201	/* open aerial map */
202	/*
203	 * turn this off; project is asleep:
204	 * https://sourceforge.net/tracker/?func=detail&aid=2897327&group_id=239475&atid=1110186
205	 * m.addLayer(new OpenLayers.Layer.XYZ("OpenAerialMap",
206	 * "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/${z}/${x}/${y}.jpg",
207	 * {name: "OpenStreetMap", attribution: "Data CC-By by <a
208	 * href='http://www.openaerialmap.org/licensing/'>OpenAerialMap</a>",
209	 * sphericalMercator: true, transitionEffect: "resize"} ));
210	 */
211
212	/* controle of google/yahoo/ve api's beschikbaar zijn.. */
213	if (gEnable) {
214		try {
215			m.addLayer(new OpenLayers.Layer.Google("google relief", {
216				type : G_PHYSICAL_MAP,
217				'sphericalMercator' : true,
218				transitionEffect : "resize"
219			}));
220			m.addLayer(new OpenLayers.Layer.Google("google sat", {
221				type : G_SATELLITE_MAP,
222				'sphericalMercator' : true,
223				transitionEffect : "resize"
224			}));
225			m.addLayer(new OpenLayers.Layer.Google("google hybrid", {
226				type : G_HYBRID_MAP,
227				'sphericalMercator' : true,
228				transitionEffect : "resize"
229			}));
230			m.addLayer(new OpenLayers.Layer.Google("google normal", {
231				type : G_NORMAL_MAP,
232				'sphericalMercator' : true,
233				transitionEffect : "resize"
234			}));
235		} catch (ol_err1) {
236		}
237	}
238
239	if (yEnable) {
240		try {
241			m.addLayer(new OpenLayers.Layer.Yahoo("yahoo", {
242				'type' : YAHOO_MAP_HYB,
243				'sphericalMercator' : true,
244				transitionEffect : resize
245			}));
246		} catch (ol_err2) {
247		}
248	}
249
250	if (veEnable) {
251		try {
252			m.addLayer(new OpenLayers.Layer.VirtualEarth("ve", {
253				'type' : VEMapStyle.Hybrid,
254				'sphericalMercator' : true,
255				transitionEffect : resize
256			}));
257		} catch (ol_err3) {
258		}
259	}
260	m.setCenter(new OpenLayers.LonLat(mapOpts.lon, mapOpts.lat).transform(
261			m.displayProjection, m.projection), mapOpts.zoom);
262	extent.extend(m.getExtent());
263
264	m.addControl(new OpenLayers.Control.KeyboardDefaults());
265	m.addControl(new OpenLayers.Control.Navigation());
266	if (mapOpts.controls === 1) {
267		/* add base controls to map */
268		m.addControl(new OpenLayers.Control.LayerSwitcher());
269		m.addControl(new OpenLayers.Control.ScaleLine({
270			geodesic : true
271		}));
272		m.addControl(new OpenLayers.Control.PanZoomBar());
273		m.addControl(new OpenLayers.Control.Graticule({
274			visible : false
275		}));
276		// TODO optioneel overzichts kaart toevoegen
277		// var overViewOpts = {layers: [wms.clone()],size: new
278		// OpenLayers.Size(120,120),projection: new
279		// OpenLayers.Projection("EPSG:900913"),opacity: 0.0,mapOptions: {
280		// /* Available resolutions are: [156543.03390000001,
281		// 78271.516950000005,
282		// 39135.758475000002, 19567.879237500001, 9783.9396187500006,
283		// 4891.9698093750003, 2445.9849046875001, 1222.9924523437501,
284		// 611.49622617187504, 305.74811308593752, 152.87405654296876,
285		// 76.43702827148438, 38.21851413574219, 19.109257067871095,
286		// 9.5546285339355475,
287		// 4.7773142669677737, 2.3886571334838869, 1.1943285667419434,
288		// 0.59716428337097172, 0.29858214168548586]*/
289		// maxResolution: 78271.51695,maxExtent: new
290		// OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
291		// /*
292		// minExtent: new OpenLayers.Bounds(1000,400000,400000,515000),*/
293		// numZoomLevels: 5},'div':OpenLayers.Util.getElement('overview')};
294		// map.addControl(new OpenLayers.Control.OverviewMap(overViewOpts));
295	}
296
297	if (mapOpts.statusbar === 1) {
298		// statusbar control: permalink
299		m.addControl(new OpenLayers.Control.Permalink(mapOpts.id
300				+ '-statusbar-link-ref'));
301		// statusbar control: mouse pos.
302		// TODO kijken naar afronding met aNumber.toFixed(0)
303		m.addControl(new OpenLayers.Control.MousePosition({
304			'div' : OpenLayers.Util.getElement(mapOpts.id
305					+ '-statusbar-mouseposition')
306		}));
307		// statusbar control: scale
308		m.addControl(new OpenLayers.Control.Scale(mapOpts.id
309				+ '-statusbar-scale'));
310		// statusbar control: attribution
311		m.addControl(new OpenLayers.Control.Attribution({
312			'div' : OpenLayers.Util.getElement(mapOpts.id + '-statusbar-text')
313		}));
314		// statusbar control: projection
315		OpenLayers.Util.getElement(mapOpts.id + '-statusbar-projection').innerHTML = m.displayProjection;
316	} else {
317		OpenLayers.Util.getElement(mapOpts.id + '-olStatusBar').display = 'none';
318	}
319
320	if (mapOpts.toolbar === 1) {
321		// buttons + panel
322		var zoomin = new OpenLayers.Control.ZoomBox({
323			title : "Zoom in"
324		});
325		var zoomout = new OpenLayers.Control.ZoomBox({
326			out : true,
327			title : "Zoom uit",
328			displayClass : "olControlZoomOut"
329		});
330		var pan = new OpenLayers.Control.DragPan({
331			title : "Verschuif"
332		});
333		// icon_query.png
334		var nav = new OpenLayers.Control.NavigationHistory();
335		m.addControl(nav);
336		var panel = new OpenLayers.Control.Panel({
337			defaultControl : zoomin,
338			displayClass : "olToolbar",
339			"div" : OpenLayers.Util.getElement(mapOpts.id + "-olToolbar")
340		});
341		panel.addControls([ zoomin, zoomout, pan ]);
342		panel.addControls([ nav.next, nav.previous ]);
343		m.addControl(panel);
344	} else {
345		OpenLayers.Util.getElement(mapOpts.id + '-olToolbar').display = 'none';
346	}
347
348	// add overlays
349	m.addLayer(new OpenLayers.Layer.OSM("Hillshade",
350			"http://toolserver.org/~cmarqu/hill/${z}/${x}/${y}.png", {
351				transitionEffect : "resize",
352				isBaseLayer : false,
353				transparent : true,
354				visibility : false
355			}));
356
357	var DocBase = DOKU_BASE;
358	if (OLmapPOI.length > 0) {
359		var markers = new OpenLayers.Layer.Vector(
360				"POI",
361				{
362					styleMap : new OpenLayers.StyleMap(
363							{
364								"default" : {
365									externalGraphic : "${img}",
366									graphicHeight : 16,
367									graphicWidth : 16,
368									graphicXOffset : 0,
369									graphicYOffset : -8,
370									graphicOpacity : "${opacity}",
371									rotation : "${angle}",
372									backgroundGraphic : DocBase
373											+ "lib/plugins/openlayersmap/icons/marker_shadow.png",
374									backgroundXOffset : 0,
375									backgroundYOffset : -4,
376									backgroundRotation : "${angle}",
377									pointRadius : 10
378								},
379								"select" : {
380									cursor : "crosshair",
381									externalGraphic : DocBase
382											+ "lib/plugins/openlayersmap/icons/marker-red.png",
383									graphicHeight : 16,
384									graphicWidth : 16,
385									graphicXOffset : 0,
386									graphicYOffset : -8,
387									graphicOpacity : 1.0,
388									rotation : "${angle}"
389								}
390							}),
391					isBaseLayer : false,
392					rendererOptions : {
393						yOrdering : true
394					}
395				});
396
397		m.addLayer(markers);
398		var features = [];
399		var lonLat;
400		for ( var j = 0; j < OLmapPOI.length; j++) {
401			var feat = new OpenLayers.Feature.Vector(
402					new OpenLayers.Geometry.Point(OLmapPOI[j].lon,
403							OLmapPOI[j].lat).transform(m.displayProjection,
404							m.projection), {
405						angle : OLmapPOI[j].angle,
406						opacity : OLmapPOI[j].opacity,
407						img : DocBase + "lib/plugins/openlayersmap/icons/"
408								+ OLmapPOI[j].img
409					});
410			feat.data = {
411				name : OLmapPOI[j].txt,
412				id : OLmapPOI[j].rowId
413			};
414			features.push(feat);
415		}
416		markers.addFeatures(features);
417		extent.extend(markers.getDataExtent());
418		m.zoomToExtent(extent);
419	}
420
421	/* GPX layer */
422	if (mapOpts.gpxfile.length > 0) {
423		var layerGPX = new OpenLayers.Layer.GML("GPS route", DocBase
424				+ "lib/exe/fetch.php?media=" + mapOpts.gpxfile, {
425			format : OpenLayers.Format.GPX,
426			formatOptions : {
427				extractWaypoints : true,
428				extractTracks : true,
429				extractStyles : true,
430				extractAttributes : true,
431				handleHeight : true,
432				maxDepth : 3
433			},
434			style : {
435				strokeColor : "#0000FF",
436				strokeWidth : 3,
437				strokeOpacity : 0.7,
438				pointRadius : 4,
439				fillColor : "#0099FF",
440				fillOpacity : 0.7
441			/*
442			 * , label:"${name}"
443			 */},
444			projection : new OpenLayers.Projection("EPSG:4326")
445		});
446		m.addLayer(layerGPX);
447		layerGPX.events.register('loadend', m, function() {
448			extent.extend(layerGPX.getDataExtent());
449			m.zoomToExtent(extent);
450		});
451
452	}
453
454	/* KML layer */
455	if (mapOpts.kmlfile.length > 0) {
456		var layerKML = new OpenLayers.Layer.GML("KML file", DocBase
457				+ "lib/exe/fetch.php?media=" + mapOpts.kmlfile, {
458			format : OpenLayers.Format.KML,
459			formatOptions : {
460				extractStyles : true,
461				extractAttributes : true,
462				maxDepth : 3
463			},
464			style : {
465				label : "${name}"
466			},
467			projection : new OpenLayers.Projection("EPSG:4326")
468		});
469		m.addLayer(layerKML);
470		layerKML.events.register('loadend', m, function() {
471			extent.extend(layerKML.getDataExtent());
472			m.zoomToExtent(extent);
473		});
474	}
475
476	// selectcontrol for layers
477	if ((m.getLayersByClass('OpenLayers.Layer.GML').length > 0)
478			|| m.getLayersByClass('OpenLayers.Layer.Vector').length > 0) {
479		selectControl = new OpenLayers.Control.SelectFeature((m
480				.getLayersByClass('OpenLayers.Layer.Vector')).concat(m
481				.getLayersByClass('OpenLayers.Layer.GML')), {
482			multiple : true,
483			hover : mapOpts.poihoverstyle,
484			onSelect : onFeatureSelect,
485			onUnselect : onFeatureUnselect
486		});
487		m.addControl(selectControl);
488		selectControl.activate();
489	}
490
491	// change/set alternative baselyr
492	try {
493		m.setBaseLayer(m.getLayersByName(mapOpts.baselyr)[0]);
494	} catch (ol_err4) {
495		m.setBaseLayer(m.layers[0]);
496	}
497	return m;
498}
499
500/**
501 * ol api flag.
502 *
503 * @type {Boolean}
504 */
505var olEnable = false;
506/**
507 * google map api flag.
508 *
509 * @type {Boolean}
510 */
511var gEnable = false;
512/**
513 * virtual earth map api flag.
514 *
515 * @type {Boolean}
516 */
517var veEnable = false;
518/**
519 * yahoo map api flag.
520 *
521 * @type {Boolean}
522 */
523var yEnable = false;
524
525/* register olInit to run with onload event. */
526addInitEvent(olInit);
527
528