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