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