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"> </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("' + mapid + '").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