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