xref: /plugin/openlayersmap/script.js (revision 219c0e2d934e4347946e2870553d1a32a01afdc1)
1/*
2 * Copyright (c) 2008-2014 Mark C. Prins <mprins@users.sf.net>
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 a full openlayers build
21 * @author Mark C. Prins <mprins@users.sf.net>
22 *
23 */
24
25/**
26 * Openlayers selectcontrol.
27 *
28 * @type {OpenLayers.Control.SelectFeature}
29 * @private
30 */
31var selectControl;
32
33/**
34 * handle feature select event.
35 *
36 * @param {OpenLayers.Feature.Vector}
37 *            selFeature the selected feature
38 */
39function onFeatureSelect(selFeature) {
40	// 'this' is selectFeature control
41	var pPos = selFeature.geometry.getBounds().getCenterLonLat();
42	// != OpenLayers.Geometry.Point
43	if (selFeature.geometry.CLASS_NAME === "OpenLayers.Geometry.LineString") {
44		try {
45			// for lines make the popup show at the cursor position
46			pPos = selFeature.layer.map.getLonLatFromViewPortPx(this.handlers.feature.evt.xy);
47		} catch (anErr) {
48			OpenLayers.Console.warn("unable to get event position; reverting to boundingbox center.");
49			pPos = selFeature.geometry.getBounds().getCenterLonLat();
50		}
51	}
52
53	var pContent = '<div class="spacer">&nbsp;</div>';
54	if (selFeature.data.rowId !== undefined) {
55		pContent += '<span class="rowId">' + selFeature.data.rowId + ': </span>';
56	}
57	if (selFeature.data.name !== undefined) {
58		pContent += '<span class="txt">' + selFeature.data.name + '</span>';
59	}
60	if (selFeature.data.ele !== undefined) {
61		pContent += '<div class="ele">elevation: ' + selFeature.data.ele + '</div>';
62	}
63	if (selFeature.data.type !== undefined) {
64		pContent += '<div>' + selFeature.data.type + '</div>';
65	}
66	if (selFeature.data.time !== undefined) {
67		pContent += '<div class="time">time: ' + selFeature.data.time + '</div>';
68	}
69	if (selFeature.data.description !== undefined) {
70		pContent += '<div class="desc">' + selFeature.data.description + '</div>';
71	}
72	// mapillary layer
73	if (selFeature.attributes.location !== undefined) {
74		pContent += '<div class="desc">' + selFeature.data.location + '</div>';
75	}
76	// mapillary layer
77	if (selFeature.attributes.image !== undefined) {
78		pContent += '<img class="img" src=' + selFeature.data.image + ' width="320" />';
79	}
80	// mapillary layer
81	if (selFeature.attributes.ca !== undefined) {
82		var angle = Math.floor(selFeature.data.ca);
83		pContent += '<div class="coord"><img src="' + DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20.png'
84				+ '" width="16" height="16" style="transform:rotate(' + angle + 'deg)" alt="' + angle + 'º"/> '+OpenLayers.i18n("compass") + angle + 'º</div>';
85	}
86
87	if (selFeature.attributes.img !== undefined) {
88		pContent += '<div class="coord"><img src="' + selFeature.attributes.img
89				+ '" width="16" height="16" style="transform:rotate(' + selFeature.attributes.angle + 'deg)" />'
90				+ '(lat;lon:' + selFeature.data.latlon + ')</div>';
91	}
92	if (pContent.length > 0) {
93		// only show when there is something to show...
94		var popup = new OpenLayersMap.Popup.FramedCloud("olPopup", pPos, null, pContent, null, true, function() {
95			selectControl.unselect(selFeature);
96			jQuery('#' + selectControl.layer.map.div.id).focus();
97		});
98		selFeature.popup = popup;
99		selFeature.layer.map.addPopup(popup);
100		jQuery('#olPopup').attr("tabindex", -1).focus();
101	}
102}
103
104/**
105 * handle feature unselect event. remove & destroy the popup.
106 *
107 * @param {OpenLayers.Feature.Vector}
108 *            selFeature the un-selected feature
109 */
110function onFeatureUnselect(selFeature) {
111	if (selFeature.popup !== null) {
112		selFeature.layer.map.removePopup(selFeature.popup);
113		selFeature.popup.destroy();
114		selFeature.popup = null;
115	}
116}
117/**
118 * Test for css support in the browser by sniffing for a css class we added
119 * using javascript added by the action plugin; this is an edge case because
120 * browsers that support javascript generally support css as well.
121 *
122 * @returns {Boolean} true when the browser supports css (and implicitly
123 *          javascript)
124 */
125function olTestCSSsupport() {
126	return (jQuery('.olCSSsupported').length > 0);
127}
128
129/**
130 * Creates a DocumentFragment to insert into the dom.
131 *
132 * @param mapid
133 *            id for the map div
134 * @param width
135 *            width for the map div
136 * @param height
137 *            height for the map div
138 * @returns a {DocumentFragment} element that can be injected into the dom
139 */
140function olCreateMaptag(mapid, width, height) {
141	var mEl = '<div id="' + mapid + '-olContainer" class="olContainer olWebOnly">'
142	// map
143	+ '<div id="' + mapid + '" tabindex="0" style="width:' + width + ';height:' + height + ';" class="olMap"></div>'
144	// statusbar
145	+ '<div id="' + mapid + '-olStatusBar" style="width:' + width + ';" class="olStatusBarContainer">' + '  <div id="'
146			+ mapid + '-statusbar-scale" class="olStatusBar olStatusBarScale">scale</div>' + '  <div id="' + mapid
147			+ '-statusbar-mouseposition" class="olStatusBar olStatusBarMouseposition"></div>' + '  <div id="' + mapid
148			+ '-statusbar-projection" class="olStatusBar olStatusBarProjection">proj</div>' + '  <div id="' + mapid
149			+ '-statusbar-text" class="olStatusBar olStatusBarText">txt</div>' + '</div>'
150			//
151			+ '</div>',
152	// fragment
153	frag = document.createDocumentFragment(),
154	// temp node
155	temp = document.createElement('div');
156	temp.innerHTML = mEl;
157	while (temp.firstChild) {
158		frag.appendChild(temp.firstChild);
159	}
160	return frag;
161}
162
163/**
164 * Create the map based on the params given.
165 *
166 * @param {Object}
167 *            mapOpts MapOptions hash {id:'olmap', width:500px, height:500px,
168 *            lat:6710200, lon:506500, zoom:13, statusbar:1, controls:1,
169 *            poihoverstyle:1, baselyr:'', kmlfile:'', gpxfile:'', geojsonfile,
170 *            summary:''}
171 * @param {Array}
172 *            OLmapPOI array with POI's [ {lat:6710300,lon:506000,txt:'instap
173 *            punt',angle:180,opacity:.9,img:'', rowId:n},... ]);
174 *
175 * @return {OpenLayers.Map} the created map
176 */
177function createMap(mapOpts, OLmapPOI) {
178	if (!olEnable) {
179		return;
180	}
181	if (!olTestCSSsupport()) {
182		olEnable = false;
183		return;
184	}
185	OpenLayers.ImgPath = DOKU_BASE + 'lib/plugins/openlayersmap/lib/img/';
186	OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
187
188	// find map element location
189	var cleartag = document.getElementById(mapOpts.id + '-clearer');
190	if (cleartag === null) {
191		return;
192	}
193	// create map element and add to document
194	var fragment = olCreateMaptag(mapOpts.id, mapOpts.width, mapOpts.height);
195	cleartag.parentNode.insertBefore(fragment, cleartag);
196
197	/** dynamic map extent. */
198	var extent = new OpenLayers.Bounds(),
199
200	/** map. */
201	m = new OpenLayers.Map({
202		div : mapOpts.id,
203		projection : 'EPSG:900913',
204		displayProjection : new OpenLayers.Projection("EPSG:4326"),
205		numZoomLevels : 22,
206		controls : [],
207		theme : null
208	});
209
210	if (osmEnable) {
211		/* add OSM map layers */
212		m.addLayer(new OpenLayers.Layer.OSM());
213
214		/* open cycle map */
215		m.addLayer(new OpenLayersMap.Layer.OCM());
216		m.addLayer(new OpenLayersMap.Layer.OCM("transport", [
217				"http://a.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png",
218				"http://b.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png",
219				"http://c.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png" ], {
220			visibility : mapOpts.baselyr === "transport"
221		}));
222		m.addLayer(new OpenLayersMap.Layer.OCM("landscape", [
223				"http://a.tile3.opencyclemap.org/landscape/${z}/${x}/${y}.png",
224				"http://b.tile3.opencyclemap.org/landscape/${z}/${x}/${y}.png",
225				"http://c.tile3.opencyclemap.org/landscape/${z}/${x}/${y}.png" ], {
226			visibility : mapOpts.baselyr === "landscape"
227		}));
228
229		m.addLayer(new OpenLayers.Layer.OSM(
230				"hike and bike map", "http://toolserver.org/tiles/hikebike/${z}/${x}/${y}.png", {
231					visibility : mapOpts.baselyr === "hike and bike map",
232					tileOptions : {
233						crossOriginKeyword : null
234					}
235				}));
236	}
237	/*
238	 * add MapQuest map layers, see:
239	 * http://developer.mapquest.com/web/products/open/map
240	 */
241	if (mqEnable) {
242		m.addLayer(new OpenLayersMap.Layer.MapQuest());
243		m.addLayer(new OpenLayersMap.Layer.MapQuest("mapquest sat", [
244				"//otile1-s.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.jpg",
245				"//otile2-s.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.jpg",
246				"//otile3-s.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.jpg",
247				"//otile4-s.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.jpg" ], {
248			// note that global coverage is provided at zoom levels 0-11. Zoom
249			// Levels 12+ are provided only in the United States (lower 48).
250			numZoomLevels : 12,
251			visibility : mapOpts.baselyr === "mapquest sat"
252		}));
253
254	}
255
256	if (gEnable) {
257		/* load google maps */
258		try {
259			m.addLayer(new OpenLayers.Layer.Google("google relief", {
260				type : google.maps.MapTypeId.TERRAIN,
261				numZoomLevels : 16,
262				animationEnabled : true,
263				visibility : mapOpts.baselyr === "google relief"
264			}));
265			m.addLayer(new OpenLayers.Layer.Google("google sat", {
266				type : google.maps.MapTypeId.SATELLITE,
267				animationEnabled : true,
268				visibility : mapOpts.baselyr === "google sat"
269			}));
270			m.addLayer(new OpenLayers.Layer.Google("google hybrid", {
271				type : google.maps.MapTypeId.HYBRID,
272				animationEnabled : true,
273				visibility : mapOpts.baselyr === "google hybrid"
274			}));
275			m.addLayer(new OpenLayers.Layer.Google("google road", {
276				animationEnabled : true,
277				visibility : mapOpts.baselyr === "google road"
278			}));
279		} catch (ol_err1) {
280			Openlayers.Console.userError('Error loading Google maps' + ol_err1);
281		}
282	}
283
284	if (bEnable && bApiKey !== '') {
285		try {
286			/* add Bing tiles */
287			m.addLayer(new OpenLayers.Layer.Bing({
288				key : bApiKey,
289				type : "Road",
290				name : "bing road",
291				visibility : mapOpts.baselyr === "bing road",
292				wrapDateLine : true,
293				attributionTemplate : '<a target="_blank" href="http://www.bing.com/maps/">'
294						+ 'Bing™</a><img src="//www.bing.com/favicon.ico" alt="Bing logo"/> ${copyrights}'
295						+ '<a target="_blank" href="http://www.microsoft.com/maps/product/terms.html">Terms of Use</a>'
296			}));
297			m.addLayer(new OpenLayers.Layer.Bing({
298				key : bApiKey,
299				type : "Aerial",
300				name : "bing sat",
301				visibility : mapOpts.baselyr === "bing sat",
302				wrapDateLine : true,
303				attributionTemplate : '<a target="_blank" href="http://www.bing.com/maps/">'
304						+ 'Bing™</a><img src="//www.bing.com/favicon.ico" alt="Bing logo"/> ${copyrights}'
305						+ '<a target="_blank" href="http://www.microsoft.com/maps/product/terms.html">Terms of Use</a>'
306			}));
307			m.addLayer(new OpenLayers.Layer.Bing({
308				key : bApiKey,
309				type : "AerialWithLabels",
310				name : "bing hybrid",
311				visibility : mapOpts.baselyr === "bing hybrid",
312				wrapDateLine : true,
313				attributionTemplate : '<a target="_blank" href="http://www.bing.com/maps/">'
314						+ 'Bing™</a><img src="//www.bing.com/favicon.ico" alt="Bing logo"/> ${copyrights}'
315						+ '<a target="_blank" href="http://www.microsoft.com/maps/product/terms.html">Terms of Use</a>'
316			}));
317		} catch (ol_errBing) {
318			Openlayers.Console.userError('Error loading Bing maps: ' + ol_errBing);
319		}
320	}
321
322	m.setCenter(new OpenLayers.LonLat(mapOpts.lon, mapOpts.lat).transform(m.displayProjection, m.projection),
323			mapOpts.zoom);
324	extent.extend(m.getExtent());
325
326	// change/set alternative baselyr
327	try {
328		m.setBaseLayer(((m.getLayersByName(mapOpts.baselyr))[0]));
329	} catch (ol_err4) {
330		m.setBaseLayer(m.layers[0]);
331	}
332
333	m.addControls([ new OpenLayers.Control.ScaleLine({
334		geodesic : true
335	}), new OpenLayers.Control.KeyboardDefaults({
336		observeElement : mapOpts.id
337	}), new OpenLayers.Control.Navigation() ]);
338
339	if (mapOpts.statusbar === 1) {
340		// statusbar control: mouse pos.
341		m.addControl(new OpenLayers.Control.MousePosition({
342			'div' : OpenLayers.Util.getElement(mapOpts.id + '-statusbar-mouseposition')
343		}));
344		// statusbar control: scale
345		m.addControl(new OpenLayers.Control.Scale(mapOpts.id + '-statusbar-scale'));
346		// statusbar control: attribution
347		m.addControl(new OpenLayers.Control.Attribution({
348			'div' : OpenLayers.Util.getElement(mapOpts.id + '-statusbar-text')
349		}));
350		// statusbar control: projection
351		OpenLayers.Util.getElement(mapOpts.id + '-statusbar-projection').innerHTML = m.displayProjection;
352	} else {
353		OpenLayers.Util.getElement(mapOpts.id + '-olStatusBar').display = 'none';
354	}
355
356	if (OLmapPOI.length > 0) {
357		var markers = new OpenLayers.Layer.Vector("POI", {
358			styleMap : new OpenLayers.StyleMap({
359				"default" : {
360					cursor : "help",
361					externalGraphic : "${img}",
362					graphicHeight : 16,
363					graphicWidth : 16,
364					// graphicXOffset : 0,
365					// graphicYOffset : -8,
366					graphicOpacity : "${opacity}",
367					rotation : "${angle}",
368					backgroundGraphic : DOKU_BASE + "lib/plugins/openlayersmap/icons/marker_shadow.png",
369					// backgroundXOffset : 0,
370					// backgroundYOffset : -4,
371					backgroundRotation : "${angle}",
372					pointRadius : 10,
373					labelXOffset : 8,
374					labelYOffset : 8,
375					labelAlign : "lb",
376					label : "${label}",
377					// fontColor : "",
378					fontFamily : "monospace",
379					fontSize : "12px",
380					fontWeight : "bold"
381				},
382				"select" : {
383					cursor : "help",
384					externalGraphic : DOKU_BASE + "lib/plugins/openlayersmap/icons/marker-red.png",
385					graphicHeight : 16,
386					graphicWidth : 16,
387					// graphicXOffset : 0,
388					// graphicYOffset : -8,
389					graphicOpacity : 1.0,
390					rotation : "${angle}"
391				}
392			}),
393			isBaseLayer : false,
394			rendererOptions : {
395				yOrdering : true
396			}
397		});
398		m.addLayer(markers);
399		var features = [];
400		for (var j = 0; j < OLmapPOI.length; j++) {
401			var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(OLmapPOI[j].lon, OLmapPOI[j].lat)
402					.transform(m.displayProjection, m.projection), {
403				angle : OLmapPOI[j].angle,
404				opacity : OLmapPOI[j].opacity,
405				img : DOKU_BASE + "lib/plugins/openlayersmap/icons/" + OLmapPOI[j].img,
406				label : OLmapPOI[j].rowId
407			});
408			var _latlon = OLmapPOI[j].lon + 'º;' + OLmapPOI[j].lat + 'º';
409			if (mapOpts.displayformat === 'DMS') {
410				_latlon = OpenLayers.Util.getFormattedLonLat(OLmapPOI[j].lon, 'lon') + ';'
411						+ OpenLayers.Util.getFormattedLonLat(OLmapPOI[j].lat, 'lat');
412			}
413			feat.data = {
414				name : OLmapPOI[j].txt,
415				rowId : OLmapPOI[j].rowId,
416				latlon : _latlon
417			};
418			features.push(feat);
419		}
420		markers.addFeatures(features);
421		extent.extend(markers.getDataExtent());
422		m.zoomToExtent(extent);
423	}
424
425	/* GPX layer */
426	if (mapOpts.gpxfile.length > 0) {
427		var layerGPX = new OpenLayers.Layer.Vector("GPS route", {
428			protocol : new OpenLayers.Protocol.HTTP({
429				url : DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.gpxfile,
430				format : new OpenLayers.Format.GPX({
431					extractWaypoints : true,
432					extractTracks : true,
433					extractStyles : true,
434					extractAttributes : true,
435					handleHeight : true,
436					maxDepth : 3
437				})
438			}),
439			style : {
440				strokeColor : "#0000FF",
441				strokeWidth : 3,
442				strokeOpacity : 0.7,
443				pointRadius : 4,
444				fillColor : "#0099FF",
445				fillOpacity : 0.7
446			// , label:"${name}"
447			},
448			projection : new OpenLayers.Projection("EPSG:4326"),
449			strategies : [ new OpenLayers.Strategy.Fixed() ]
450		});
451		m.addLayer(layerGPX);
452		layerGPX.events.register('loadend', m, function() {
453			extent.extend(layerGPX.getDataExtent());
454			m.zoomToExtent(extent);
455		});
456	}
457
458	/* GeoJSON layer */
459	if (mapOpts.geojsonfile.length > 0) {
460		var layerGJS = new OpenLayers.Layer.Vector("json data", {
461			protocol : new OpenLayers.Protocol.HTTP({
462				url : DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.geojsonfile,
463				format : new OpenLayers.Format.GeoJSON({
464					ignoreExtraDims : true
465				})
466			}),
467			style : {
468				strokeColor : "#FF00FF",
469				strokeWidth : 3,
470				strokeOpacity : 0.7,
471				pointRadius : 4,
472				fillColor : "#FF99FF",
473				fillOpacity : 0.7
474			// , label:"${name}"
475			},
476			projection : new OpenLayers.Projection("EPSG:4326"),
477			strategies : [ new OpenLayers.Strategy.Fixed() ]
478		});
479		m.addLayer(layerGJS);
480		layerGJS.events.register('loadend', m, function() {
481			extent.extend(layerGJS.getDataExtent());
482			m.zoomToExtent(extent);
483		});
484	}
485
486	/* KML layer */
487	if (mapOpts.kmlfile.length > 0) {
488		var layerKML = new OpenLayers.Layer.Vector("KML file", {
489			protocol : new OpenLayers.Protocol.HTTP({
490				url : DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.kmlfile,
491				format : new OpenLayers.Format.KML({
492					extractStyles : true,
493					extractAttributes : true,
494					maxDepth : 3
495				})
496			}),
497			style : {
498				label : "${name}"
499			},
500			projection : new OpenLayers.Projection("EPSG:4326"),
501			strategies : [ new OpenLayers.Strategy.Fixed() ]
502		});
503		m.addLayer(layerKML);
504		layerKML.events.register('loadend', m, function() {
505			extent.extend(layerKML.getDataExtent());
506			m.zoomToExtent(extent);
507		});
508	}
509
510	// selectcontrol for layers
511	if ((m.getLayersByClass('OpenLayers.Layer.GML').length > 0)
512			|| m.getLayersByClass('OpenLayers.Layer.Vector').length > 0) {
513		selectControl = new OpenLayers.Control.SelectFeature((m.getLayersByClass('OpenLayers.Layer.Vector')).concat(m
514				.getLayersByClass('OpenLayers.Layer.GML')), {
515			hover : mapOpts.poihoverstyle,
516			onSelect : onFeatureSelect,
517			onUnselect : onFeatureUnselect
518		});
519		m.addControl(selectControl);
520		selectControl.activate();
521
522		// keyboard select control
523		var iControl = new OpenLayersMap.Control.KeyboardClick({
524			observeElement : mapOpts.id,
525			selectControl : selectControl
526		});
527		m.addControl(iControl);
528	}
529
530	if (mapOpts.controls === 1) {
531		/* add base controls to map */
532		m.addControls([ new OpenLayersMap.Control.LayerSwitcher(), new OpenLayers.Control.Graticule({
533			visible : false
534		}), new OpenLayersMap.Control.OverviewMap({
535			mapOptions : {
536				theme : null
537			}
538		}), new OpenLayersMap.Control.Zoom(), new OpenLayersMap.Control.Fullscreen() ]);
539
540		// add hillshade, since this is off by default only add when we have a
541		// layerswitcher
542		m.addLayer(new OpenLayers.Layer.OSM("Hillshade", "http://toolserver.org/~cmarqu/hill/${z}/${x}/${y}.png", {
543			isBaseLayer : false,
544			transparent : true,
545			visibility : false,
546			displayOutsideMaxExtent : true,
547			attribution : '',
548			tileOptions : {
549				crossOriginKeyword : null
550			}
551		}));
552	}
553
554	return m;
555}
556
557/** init. */
558function olInit() {
559	if (olEnable) {
560		var _i = 0;
561		// create the maps in the page
562		for (_i = 0; _i < olMapData.length; _i++) {
563			var _id = olMapData[_i].mapOpts.id;
564			olMaps[_id] = createMap(olMapData[_i].mapOpts, olMapData[_i].poi);
565
566			// set max-width on help pop-over
567			jQuery('#' + _id).parent().parent().find('.olMapHelp').css('max-width', olMapData[_i].mapOpts.width);
568
569			// shrink the map width to fit inside page container
570			var _w = jQuery('#' + _id + '-olContainer').parent().innerWidth();
571			if (parseInt(olMapData[_i].mapOpts.width) > _w) {
572				jQuery('#' + _id).width(_w);
573				jQuery('#' + _id + '-olStatusBar').width(_w);
574				jQuery('#' + _id).parent().parent().find('.olMapHelp').width(_w);
575				olMaps[_id].updateSize();
576			}
577		}
578
579		// hide the table(s) with POI by giving it a print-only style
580		jQuery('.olPOItableSpan').addClass('olPrintOnly');
581		// hide the static map image(s) by giving it a print only style
582		jQuery('.olStaticMap').addClass('olPrintOnly');
583		// add help button with toggle.
584		jQuery('.olWebOnly > .olMap')
585				.prepend(
586						'<div class="olMapHelpButtonDiv">'
587								+ '<button onclick="jQuery(\'.olMapHelp\').toggle(500);" class="olMapHelpButton olHasTooltip"><span>'
588								+ OpenLayers.i18n("toggle_help") + '</span>?</button></div>');
589		// toggle to switch dynamic vs. static map
590		jQuery('.olMapHelp').before(
591				'<div class="a11y"><button onclick="jQuery(\'.olPrintOnly\').toggle();jQuery(\'.olWebOnly\').toggle();">'
592						+ OpenLayers.i18n("toggle_dynamic_map") + '</button></div>');
593	}
594}
595
596/**
597 * ol api flag.
598 *
599 * @type {Boolean}
600 */
601var olEnable = false,
602/**
603 * An array with data for each map in the page.
604 *
605 * @type {Array}
606 */
607olMapData = [],
608/**
609 * Holds a reference to all of the maps on this page with the map's id as key.
610 * Can be used as an extension point.
611 *
612 * @type {Object}
613 */
614olMaps = new Object(),
615/**
616 * MapQuest tiles flag.
617 *
618 * @type {Boolean}
619 */
620mqEnable = false,
621/**
622 * google map api flag.
623 *
624 * @type {Boolean}
625 */
626gEnable = false,
627/**
628 * Bing tiles flag.
629 *
630 * @type {Boolean}
631 */
632bEnable = false,
633/**
634 * Bing API key.
635 *
636 * @type {String}
637 */
638bApiKey = '',
639/**
640 * MapQuest API key.
641 *
642 * @type {String}
643 */
644mqApiKey = '',
645/**
646 * Google API key.
647 *
648 * @type {String}
649 */
650gApiKey = '',
651/**
652 * OSM tiles flag.
653 *
654 * @type {Boolean}
655 */
656osmEnable = true,
657/**
658 * CSS support flag.
659 *
660 * @type {Boolean}
661 */
662olCSSEnable = true;
663
664/* register olInit to run with onload event. */
665jQuery(olInit);
666