1var pictoHoverFeatures = []; 2var barreauHoverFeatures = []; 3var zoneHoverFeatures = []; 4var blinkFeatureGeojson = []; 5var timer; 6 7$(document).ready(function (e) { 8 // Affiche un message si le fichier const internet n'est pas présent 9 if (typeof $.turbolead.get('CONST_INTERNET_JS') === 'undefined') { 10 console.log( 11 "Attention ! Le fichier constInternet n'est pas inclus. Certaines fonctionnalités peuvent ne pas fonctionner." 12 ); 13 } 14 15 // Modifie les configurations de la couche 16 DDEInitializeOsmRewriteLayerConfig(); 17 18 //carte principale 19 if ($('#map').length) { 20 DDEInitializeOsmMasterMap('map'); 21 } 22 23 //carte export 24 if ($('#OSMExportMap').length) { 25 DDEInitializeOsmExportMap('OSMExportMap'); 26 } 27 28 var urlParams = new URLSearchParams(window.location.search); 29 if (urlParams.has('lat') && urlParams.has('lng') && urlParams.has('id')) { 30 var idRepere = urlParams.get('id'); 31 var maxTentative = 10; 32 var i = 0; 33 function checkFeatureLoaded() { 34 setTimeout(function () { 35 i++; 36 if ((feature = getRepereById(idRepere))) { 37 i = maxTentative; 38 zoomInEvent(feature); 39 } 40 41 if (i < maxTentative) { 42 checkFeatureLoaded(); 43 } 44 }, 100); 45 } 46 checkFeatureLoaded(); 47 } 48}); 49 50function zoomInEvent(feature) { 51 if ($(window).width() <= 980) { 52 $('.NavigationTab-item[aria-selected="true"]').click(); 53 } 54 let coordiantes = feature.getGeometry().getCoordinates();
55 setViewZoomAndCenter(15, coordiantes[0], coordiantes[1]); 56 var addPopupOnClick = function (event) { 57 if (!event.frameState.animate) { 58 //simule un clique au pixel des coordonées. 59 var pixel = oMap.getPixelFromCoordinate(coordiantes); 60 var evt = { 61 type: 'singleclick', 62 pixel: pixel, 63 originalEvent: { 64 pixel: pixel, 65 }, 66 }; 67 oMap.dispatchEvent(evt); 68 oMap.un('postrender', addPopupOnClick); 69 } 70 }; 71 oMap.on('postrender', addPopupOnClick); 72} 73 74/** 75 * Réécrit les codes des couches 76 */ 77function DDEInitializeOsmRewriteLayerConfig() { 78 // Récupère les calques par type 79 var ddeOsmCalquesByType = $.turbolead.get('calques_by_type'); 80 if (typeof ddeOsmCalquesByType === 'undefined') { 81 return; 82 } 83 84 var calquesByTypes = $.turbolead.get('calques_by_type'); 85 86 // Réaffecte les types aux calques 87 if ( 88 typeof calquesByTypes['repere'] !== 'undefined' && 89 typeof layerConfig.repere.sublayer !== 'undefined' && 90 layerConfig.repere.sublayer.length > 0 91 ) { 92 // Récupère les calques 93 let calquesByCode = calquesByTypes['repere']; 94 95 for (var i = 0; i < layerConfig.repere.sublayer.length; i++) { 96 // Récupère le nom et les codes de la couche 97 var subLayerName = layerConfig.repere.sublayer[i].name; 98 var subLayerCodes = layerConfig.repere.sublayer[i].code; 99 100 // Récupère les nouveaux codes de la couche 101 var subLayerNewCodes = DDEGetLayerCodes(subLayerName, subLayerCodes, calquesByCode); 102 103 // Redéfinie les codes de la couche 104 layerConfig.repere.sublayer[i].code = subLayerNewCodes; 105 } 106 } 107 108 // Réaffecte les types aux calques 109 if ( 110 typeof calquesByTypes['barreau'] !== 'undefined' && 111 typeof layerConfig.barreau.sublayer !== 'undefined' && 112 layerConfig.barreau.sublayer.length > 0 113 ) { 114 // Récupère les calques 115 calquesByCode = calquesByTypes['barreau']; 116 117 for (var i = 0; i < layerConfig.barreau.sublayer.length; i++) { 118 // Récupère le nom et les codes de la couche 119 var subLayerName = layerConfig.barreau.sublayer[i].name; 120 var subLayerCodes = layerConfig.barreau.sublayer[i].code; 121 122 // Récupère les nouveaux codes de la couche 123 var subLayerNewCodes = DDEGetLayerCodes(subLayerName, subLayerCodes, calquesByCode); 124 125 // Redéfinie les codes de la couche 126 layerConfig.barreau.sublayer[i].code = subLayerNewCodes; 127 } 128 } 129 130 // Réaffecte les types aux calques 131 if ( 132 typeof calquesByTypes['zone'] !== 'undefined' && 133 typeof layerConfig.zone.sublayer !== 'undefined' && 134 layerConfig.zone.sublayer.length > 0 135 ) { 136 // Récupère les calques 137 calquesByCode = calquesByTypes['zone']; 138 139 for (var i = 0; i < layerConfig.zone.sublayer.length; i++) { 140 // Récupère le nom et les codes de la couche 141 var subLayerName = layerConfig.zone.sublayer[i].name; 142 var subLayerCodes = layerConfig.zone.sublayer[i].code; 143 144 // Récupère les nouveaux codes de la couche 145 var subLayerNewCodes = DDEGetLayerCodes(subLayerName, subLayerCodes, calquesByCode); 146 147 // Redéfinie les codes de la couche 148 layerConfig.zone.sublayer[i].code = subLayerNewCodes; 149 } 150 } 151} 152 153/** 154 * Retourne les codes de la couche en prenant en compte le paramétrage du logiciel 155 * @param layerName 156 * @param layerCodes 157 * @param calquesByCode 158 * @returns 159 */ 160function DDEGetLayerCodes(layerName, layerCodes, calquesByCode) { 161 var newCodes = []; 162 for (var i = 0; i < layerCodes.length; i++) { 163 // Si le code n'est pas associé à un calque dans le paramétrage, 164 // on laisse le code dans la couche 165 if (typeof calquesByCode[layerCodes[i]] === 'undefined') { 166 newCodes.push(layerCodes[i]); 167 } 168 } 169 170 // Ajoute les codes associés à la couche 171 for (var code in calquesByCode) { 172 if (calquesByCode[code] === layerName) { 173 newCodes.push(code); 174 } 175 } 176 177 return newCodes; 178} 179 180/** 181 * Initialise la carte principale de l'interface 182 * 183 * @param string elementId: identifiant de l'élément du DOm qui va contenir la carte 184 * 185 * @return void 186 */ 187function DDEInitializeOsmMasterMap(elementId) { 188 // Commentaire général 189 // Récupère le titre 190 var ddeOsmGeneralCommentTitle = $.turbolead.get('config_generalcomment_title'); 191 if (typeof ddeOsmGeneralCommentTitle === 'undefined' || ddeOsmGeneralCommentTitle === '') { 192 // Définie une valeur par défaut si non définie 193 ddeOsmGeneralCommentTitle = 'Conditions de circulation'; 194 } 195 196 // Récupère la largeur 197 var ddeOsmGeneralCommentWidth = $.turbolead.get('config_generalcomment_width'); 198 if (typeof ddeOsmGeneralCommentWidth === 'undefined' || ddeOsmGeneralCommentWidth === '') { 199 // Définie une valeur par défaut si non définie 200 ddeOsmGeneralCommentWidth = 400; 201 } 202 203 // Récupère la hauteur 204 var ddeOsmGeneralCommentHeight = $.turbolead.get('config_generalcomment_height'); 205 if (typeof ddeOsmGeneralCommentHeight === 'undefined' || ddeOsmGeneralCommentHeight === '') { 206 // Définie une valeur par défaut si non définie 207 ddeOsmGeneralCommentHeight = 300; 208 } 209 210 // Récupère le temps d'affichage 211 var ddeOsmGeneralCommentTimer = $.turbolead.get('config_generalcomment_timer'); 212 if (typeof ddeOsmGeneralCommentTimer === 'undefined' || ddeOsmGeneralCommentTimer === '') { 213 // Définie une valeur par défaut si non définie 214 ddeOsmGeneralCommentTimer = 10000; 215 } else {
216 // Convertit le temps en secondes en millisecondes 217 ddeOsmGeneralCommentTimer = parseFloat(ddeOsmGeneralCommentTimer) * 1000.0; 218 } 219 220 // Affiche le commentaire general 221 if ($('#commentaire-general').length && $('#commentaire-general').data('affichage') === 1) { 222 showDialogBox( 223 ddeOsmGeneralCommentTitle, 224 ddeOsmGeneralCommentHeight, 225 ddeOsmGeneralCommentWidth, 226 'commentaire-general', 227 '', 228 ddeOsmGeneralCommentTimer 229 ); 230 } 231 232 // Configure le bouton d'affichage du commentaire general 233 var commentLink = $('a.BodyHeader-morebtn'); 234 if (commentLink.length) { 235 // Redéfinit la taille du popup 236 var parts = commentLink.attr('href').split('?'); 237 for (var i = 0; i < parts.length; i++) { 238 var subparts = parts[i].split('&'); 239 for (var j = 0; j < subparts.length; j++) { 240 if (subparts[j].substring(0, 6) == 'width=') { 241 subparts[j] = 'width=' + ddeOsmGeneralCommentWidth; 242 } 243 if (subparts[j].substring(0, 7) == 'height=') { 244 subparts[j] = 'height=' + ddeOsmGeneralCommentHeight; 245 } 246 } 247 parts[i] = subparts.join('&'); 248 } 249 commentLink.attr('href', parts.join('?')); 250 commentLink.data('title', ddeOsmGeneralCommentTitle); 251 252 // Met en place le clignotement du bouton 253 if ($('#commentaire-general').length && $('#commentaire-general').data('clignot') === 1) { 254 function blinkCommentLink() { 255 commentLink.fadeIn(1000).delay(500).fadeOut(1000, blinkCommentLink); 256 } 257 blinkCommentLink(); 258 } 259 } 260 261 // Parametres de la carte 262 var oViewOption = getMapParameters(elementId); 263 oViewOption.layers = createGroupeTile(tileConfig); 264 265 // Insertion de la carte 266 DDEAddMap(oViewOption); 267 268 // Insertion des controleurs 269 DDEAddControl(elementId); 270 271 //les calques 272 DDEAddAllLayer(layerConfig); 273 274 //selecteur de maps 275 if ($('#select-maps').length) { 276 $('#select-maps').change(function () { 277 toggleTileVisibilityByName($(this).val()); 278 }); 279 } 280 281 //creation des overlay 282 var oOverlaySingleClick = initializePopUp('popup', 'popover', true); 283 var oOverlayPointermove = initializePopUp('popup_pointermove', 'popover_pointermove', false); 284 285 //Ajout des popups "singleclick" 286 oMap.on('singleclick', function (evt) { 287 if (evt.dragging) return; 288 var clickOnCluster = manageClusterInteraction(evt); 289 if (!clickOnCluster) { 290 renderPopUp( 291 evt, 292 oOverlaySingleClick.overlay, 293 oOverlaySingleClick.title, 294 oOverlaySingleClick.content, 295 true, 296 oOverlayPointermove.overlay 297 ); 298 renderBarreauPictos(evt); 299 } 300 }); 301 302 //Ajout des popups "pointermove" 303 oMap.on('pointermove', function (evt) { 304 if (evt.dragging) return; 305 DDEDetectMouseOver(evt); 306 var showPopupPointermove = true; 307 if (oOverlaySingleClick.overlay.getPosition() !== undefined) showPopupPointermove = false; 308 renderPopUp( 309 evt, 310 oOverlayPointermove.overlay, 311 oOverlayPointermove.title, 312 oOverlayPointermove.content, 313 showPopupPointermove, 314 oOverlaySingleClick.overlay 315 ); 316 if (showPopupPointermove) { 317 renderBarreauPictos(evt); 318 } 319 }); 320 321 //gestion de la sélection d'une déviation 322 if (typeof layerConfig.deviation !== 'undefined') { 323 var layerDeviation = getLayerByName('layer-deviation'); 324 var selectDeviation = new ol.interaction.Select({ 325 condition: function (evt) { 326 return evt.type === 'singleclick'; 327 }, 328 layers: [layerDeviation], 329 style: complexeStyle, 330 toggleCondition: ol.events.condition.never, 331 filter: function (feature, layer) { 332 return ( 333 feature instanceof ol.Feature && 334 layer instanceof ol.layer.Vector && 335 layer.get('name') === 'layer-deviation' && 336 feature.get('type') === '_DEVIATION' && 337 feature.get('type_deviation') === 'ROUTE_COUPEE' 338 ); 339 }, 340 }); 341 oMap.addInteraction(selectDeviation); 342 } 343 344 //statistiques internes 345 if ( 346 typeof internalStatistics !== 'undefined' && 347 typeof internalStatistics.enable !== 'undefined' && 348 internalStatistics.enable === true && 349 typeof internalStatistics.urlFolder !== 'undefined' && 350 typeof internalStatistics.filePrefix !== 'undefined' 351 ) { 352 var oInternalStatistics = new statistiqueInterne(internalStatistics.urlFolder, internalStatistics.filePrefix); 353 354 //clic et rollover 355 oMap.on(['pointermove', 'singleclick'], function (evt) { 356 if (evt.dragging) return; 357 handleFeatureInteractionForStatistiqueInterne(evt, oInternalStatistics); 358 }); 359 360 //fermeture de session 361 window.onbeforeunload = function () { 362 oInternalStatistics.remplirTableauStat('fermeture', '', ''); 363 oInternalStatistics.envoyerStatistiques();
364 return undefined; 365 }; 366 } 367} 368 369/** 370 * Initialise la carte de l'export des archives 371 * 372 * @param string elementId: identifiant de l'élément du DOm qui va contenir la carte 373 * 374 * @return void 375 */ 376function DDEInitializeOsmExportMap(elementId) { 377 //Parametres de la carte 378 var oViewOption = getMapParameters(elementId); 379 380 //Insertion de la carte 381 DDEAddMap(oViewOption); 382 383 //Insertion des controleurs 384 DDEAddControl(elementId); 385 386 //Liste des calques visibles 387 layerConfig['barreau'].visibility = 388 typeof $('#' + elementId).data('barreauvisible') !== 'undefined' && 389 $('#' + elementId).data('barreauvisible') === 1 390 ? true 391 : false; 392 layerConfig['zone'].visibility = 393 typeof $('#' + elementId).data('zonevisible') !== 'undefined' && $('#' + elementId).data('zonevisible') === 1 394 ? true 395 : false; 396 layerConfig['repere'].visibility = 397 typeof $('#' + elementId).data('reperevisible') !== 'undefined' && 398 $('#' + elementId).data('reperevisible') === 1 399 ? true 400 : false; 401 402 //Insertion des calques 403 DDEAddAllLayer(layerConfig); 404 405 //Insertion du cadre de slection et zoom 406 DDEAddDragBoxInteraction(); 407} 408 409/** 410 * Ajout de l'interaction de cadre de selection 411 * 412 * @param void 413 * 414 * @return void 415 */ 416function DDEAddDragBoxInteraction() { 417 var oLayerBarreau = getLayerByName('layer-barreau'), 418 oLayerZone = getLayerByName('layer-zone'), 419 oLayerRepere = getLayerByName('layer-repere'); 420 421 //Ajout de l'interaction de selection 422 var oSelect = new ol.interaction.Select({ 423 layers: [oLayerBarreau, oLayerZone, oLayerRepere], 424 }); 425 oMap.addInteraction(oSelect); 426 var tSelectedFeature = oSelect.getFeatures(); 427 428 //Ajout de l'interaction de DragBox 429 var oDragBox = new ol.interaction.DragBox({ 430 condition: ol.events.condition.platformModifierKeyOnly, 431 }); 432 oMap.addInteraction(oDragBox); 433 434 //Vider la selection au clique sur la carte ou d'une nouvelle selection 435 oDragBox.on('boxstart', function () { 436 tSelectedFeature.clear(); 437 }); 438 439 //capturer les objets en intersection avec le cadre de selection 440 oDragBox.on('boxend', function () { 441 var tExtent = oDragBox.getGeometry().getExtent(); 442 443 //calque des barreaux 444 if (oLayerBarreau !== null && oLayerBarreau.getVisible()) { 445 oLayerBarreau.getSource().forEachFeatureIntersectingExtent(tExtent, function (feature) { 446 if (typeof feature.getId() === 'number') { 447 tSelectedFeature.push(feature); 448 } 449 }); 450 } 451 452 //calque des zones 453 if (oLayerZone !== null && oLayerZone.getVisible()) { 454 oLayerZone.getSource().forEachFeatureIntersectingExtent(tExtent, function (feature) { 455 if (typeof feature.getId() === 'number') { 456 tSelectedFeature.push(feature); 457 } 458 }); 459 } 460 461 //calque des repere 462 if (oLayerRepere !== null && oLayerRepere.getVisible()) { 463 oLayerRepere.getSource().forEachFeatureIntersectingExtent(tExtent, function (feature) { 464 tSelectedFeature.push(feature); 465 }); 466 } 467 }); 468 469 //changement de la selection 470 tSelectedFeature.on(['add', 'remove'], function () { 471 var tInfo = { 472 barreau: [], 473 zone: [], 474 repere: [], 475 }, 476 sType = ''; 477 478 tSelectedFeature.getArray().map(function (feature) { 479 sType = feature.get('type'); 480 if (sType === '_BARREAU') { 481 tInfo['barreau'].push(feature.get('id_archive')); 482 } else if (sType === '_ZONE') { 483 tInfo['zone'].push(feature.get('id_archive')); 484 } else { 485 tInfo['repere'].push(feature.get('id_archive')); 486 } 487 feature.changed(); 488 }); 489
490 //affichage 491 $('#exportbarreauselection').val(tInfo['barreau'].join('|')); 492 $('#exportzoneselection').val(tInfo['zone'].join('|')); 493 $('#exportrepereselection').val(tInfo['repere'].join('|')); 494 }); 495} 496 497/** 498 * Retourner les paramétres de la carte à partir de l'élément du DOM qui va contenir la carte 499 * 500 * @param string elementId: identifiant de l'élément du DOm qui va contenir la carte 501 * 502 * @return string{} 503 */ 504function getMapParameters(elementId) { 505 var sMapId = '#' + elementId, 506 oViewOption = {}, 507 centerLongitude = 508 typeof $(sMapId).data('centerlon') !== 'undefined' ? parseFloat($(sMapId).data('centerlon')) : 0, 509 centerLatitude = 510 typeof $(sMapId).data('centerlat') !== 'undefined' ? parseFloat($(sMapId).data('centerlat')) : 0; 511 512 sUrlAjax = String($(sMapId).data('urlajax')); 513 514 oViewOption.target = elementId; 515 oViewOption.center = ol.proj.transform( 516 [centerLongitude, centerLatitude], 517 defaultDataProjection, 518 defaultOsmProjection 519 ); 520 oViewOption.extent = getMapExtent(elementId); 521 oViewOption.zoom = typeof $(sMapId).data('zoom') !== 'undefined' ? parseInt($(sMapId).data('zoom'), 10) : 0; 522 oViewOption.minZoom = 523 typeof $(sMapId).data('minzoom') !== 'undefined' ? parseInt($(sMapId).data('minzoom'), 10) : 0; 524 oViewOption.maxZoom = 525 typeof $(sMapId).data('maxzoom') !== 'undefined' ? parseInt($(sMapId).data('maxzoom'), 10) : 28; 526 527 var fResolution = 528 typeof $(sMapId).data('resolution') !== 'undefined' && $(sMapId).data('resolution') !== '' 529 ? parseFloat($(sMapId).data('resolution')) 530 : undefined, 531 tResolutions, 532 sResolutions = 533 typeof $(sMapId).data('resolutions') !== 'undefined' && $(sMapId).data('resolutions') !== '' 534 ? String($(sMapId).data('resolutions')) 535 : undefined; 536 if (fResolution !== undefined && !isNaN(fResolution) && sResolutions !== undefined && sResolutions !== '') { 537 var tResolutionsTmp = sResolutions.split('|'); 538 if (Array.isArray(tResolutionsTmp) && tResolutionsTmp.length !== 0) { 539 tResolutions = []; 540 var i = 0, 541 sValue = '', 542 nValue = 0; 543 for (i = 0; i < tResolutionsTmp.length; i++) { 544 sValue = tResolutionsTmp[i].trim(); 545 nValue = parseFloat(sValue); 546 if (nValue !== 0 && !isNaN(nValue)) tResolutions.push(nValue); 547 } 548 } 549 550 if (tResolutions.length !== 0) { 551 oViewOption.resolution = fResolution; 552 oViewOption.resolutions = tResolutions; 553 } 554 } 555 556 return oViewOption; 557} 558 559/** 560 * Ajouter une carte OpenLayers 561 * 562 * @param option {object} : paramétres de la vue de la carte 563 * option.target {string} : identifiant de l'éélment DOM qui va contenir la carte 564 * option.center {float[]|undefined} : coordonnées du centre de la carte[longitude,latitude] 565 * option.extent {float[]|undefined} : contraintes sur le centre de la carte 566 * option.zoom {integer|undefine} : zoom initial de la carte 567 * option.minZoom {integer|undefine} : zoom minimal de la carte 568 * option.maxZoom {integer|undefine} : zoom minimal de la carte 569 * option.resolution {float|undefine} : resolution initial de la carte 570 * option.resolutions {float[]|undefine} : tableau des resolutions de la carte 571 * 572 * @return void 573 */ 574function DDEAddMap(option) { 575 // Vue de la carte 576 oView = new ol.View({ 577 center: option.center, 578 zoom: option.zoom, 579 }); 580 //extent 581 if (typeof option.extent !== 'undefined') oView.set('extent', option.extent, true); 582 //minZoom 583 if (typeof option.minZoom !== 'undefined') oView.set('minZoom', option.minZoom, true); 584 //maxZoom 585 if (typeof option.maxZoom !== 'undefined') oView.set('maxZoom', option.maxZoom, true); 586 //resolution 587 if (typeof option.resolution !== 'undefined') oView.setResolution(option.resolution); 588 //resolutions 589 if (typeof option.resolutions !== 'undefined') oView.set('resolutions', option.resolutions, true); 590 591 //La carte 592 oMap = new ol.Map({ 593 target: option.target, 594 controls: [], 595 view: oView, 596 });
597 //layers 598 if (typeof option.layers !== 'undefined') { 599 oMap.addLayer(option.layers); 600 } else { 601 //carte OSM par defaut 602 oMap.addLayer( 603 new ol.layer.Tile({ 604 source: new ol.source.OSM(), 605 }) 606 ); 607 } 608} 609 610/** 611 * Création du groupe des cartes (tuile) 612 * 613 * @param layerConf {object} : parametres de configuration du calque 614 * @returns {ol.layer.Group} 615 */ 616function createGroupeTile(layerConf) { 617 var layers = []; 618 var conf = {}; 619 620 for (var i in layerConf.layers) { 621 conf = layerConf.layers[i]; 622 if (conf) { 623 switch (conf.type) { 624 case 'TileWMS': 625 layers.push(createWmsTile(conf)); 626 break; 627 case 'OSM': 628 layers.push(createOsmTile(conf)); 629 break; 630 case 'XYZ': 631 layers.push(createXyzTile(conf)); 632 break; 633 case 'Stamen': 634 layers.push(createStamenTile(conf)); 635 break; 636 default: 637 break; 638 } 639 } else { 640 layers.push(createOsmTile(conf)); 641 } 642 } 643 644 return new ol.layer.Group({ 645 name: layerConf.groupName, 646 label: layerConf.groupLabel, 647 layers: layers, 648 }); 649} 650 651/** 652 * création d'un calque de tuile OSM 653 * 654 * @param layerConf {object} : parametres de configuration du calque 655 * @returns {ol.layer.Tile} 656 */ 657function createOsmTile(layerConf) { 658 return new ol.layer.Tile({ 659 name: layerConf.name, 660 label: layerConf.label, 661 visible: layerConf.visible, 662 source: new ol.source.OSM(), 663 }); 664} 665 666/** 667 * création d'un calque de tuile XYZ 668 * 669 * @param layerConf {object} : parametres de configuration du calque 670 * @returns {ol.layer.Tile} 671 */ 672function createXyzTile(layerConf) { 673 var sUrl = 674 typeof layerConf.url !== 'undefined' && layerConf.url !== '' 675 ? layerConf.url 676 : 'http://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png'; 677 return new ol.layer.Tile({ 678 name: layerConf.name, 679 label: layerConf.label, 680 visible: layerConf.visible, 681 source: new ol.source.XYZ({ 682 attributions: [ 683 new ol.Attribution({ 684 html: layerConf.attribution, 685 }), 686 ], 687 url: sUrl, 688 }), 689 }); 690} 691 692/** 693 * création d'un calque de tuile WMS 694 * 695 * @param layerConf {object} : parametres de configuration du calque 696 * @returns {ol.layer.Tile} 697 */ 698function createWmsTile(layerConf) { 699 return new ol.layer.Tile({ 700 name: layerConf.name, 701 label: layerConf.label, 702 visible: layerConf.visible, 703 source: new ol.source.TileWMS({ 704 url: layerConf.url, 705 params: { LAYERS: layerConf.layer, TILED: true }, 706 attributions: [ 707 new ol.Attribution({ 708 html: 'WMS © ' + layerConf.attribution, 709 }), 710 ], 711 }), 712 }); 713} 714 715/** 716 * création d'un calque de tuile Stamen 717 * 718 * @param layerConf {object} : parametres de configuration du calque 719 * @returns {ol.layer.Tile} 720 */ 721function createStamenTile(layerConf) { 722 return new ol.layer.Tile({ 723 name: layerConf.name, 724 label: layerConf.label, 725 visible: layerConf.visible, 726 source: new ol.source.Stamen({ layer: layerConf.layer }), 727 }); 728} 729 730/** 731 * fonction de geolocalisation 732 */ 733function DDEGeolocateMe() { 734 var geolocation = new ol.Geolocation({ 735 projection: oView.getProjection(), 736 }); 737 geolocation.setTracking(true); 738 739 //on dispose d'une ancienne localisation 740 if (typeof defaultGeolocation !== 'undefined') { 741 oView.setCenter(defaultGeolocation); 742 } 743 744 //gestion d'une bonne gelocalisation 745 geolocation.once('change', function (evt) { 746 var tPostion = geolocation.getPosition(); 747 var tExtent = getMapExtent(); 748 var sTitre = '', 749 sMessage = ''; 750 var bAddParagraph = false; 751 if (ol.extent.containsCoordinate(tExtent, tPostion)) { 752 oView.setCenter(tPostion); 753 defaultGeolocation = tPostion; 754 } else { 755 sTitre = 'Géolocalisation hors périmètre'; 756 sMessage = 'La fonction de géolocalisation ne fonctionne pas en dehors du périmètre du département.'; 757 bAddParagraph = addParagraphInHiddenDiv('message-geolocation', '', sMessage); 758 if (bAddParagraph) showDialogBox(sTitre, 100, 400, 'message-geolocation', '', 5000); 759 } 760 });
761 762 //gestion d'une erreur de geolocalisation 763 geolocation.on('error', function (error) { 764 var sTitre = 'Erreur de géolocalisation'; 765 var sMessage = 'La fonction de géolocalisation a rencontré un problème :<br>"' + error.message + '"'; 766 var bAddParagraph = addParagraphInHiddenDiv('message-geolocation', '', sMessage); 767 if (bAddParagraph) showDialogBox(sTitre, 150, 400, 'message-geolocation', '', 5000); 768 }); 769} 770 771/** 772 * Ajouter le controleur de geolocalisation 773 */ 774function addGeolocationControl() { 775 //défintion d'un espace de nom pour l'application 776 window.app = window.app || {}; 777 var app = window.app; 778 779 /** 780 * @constructor 781 * @extends {ol.control.Control} 782 * @param {Object=} opt_options Control options. 783 */ 784 app.GeolocationControl = function (opt_options) { 785 var options = opt_options || {}; 786 787 var button = document.createElement('button'); 788 button.innerHTML = controlConfig.geolocation.innerHTML; 789 790 var handleGeolocation = function (e) { 791 DDEGeolocateMe(); 792 }; 793 794 button.addEventListener('click', handleGeolocation, false); 795 button.addEventListener('touchstart', handleGeolocation, false); 796 797 var element = document.createElement('div'); 798 element.className = 'ol-geolocation ol-unselectable ol-control'; 799 element.appendChild(button); 800 801 ol.control.Control.call(this, { 802 element: element, 803 target: options.target, 804 }); 805 }; 806 ol.inherits(app.GeolocationControl, ol.control.Control); 807} 808 809/** 810 * Ajouter les controleurs de le carte 811 * 812 * @param string elementId: identifiant de l'élément du DOm qui va contenir la carte 813 * 814 * @return void 815 */ 816function DDEAddControl(elementId) { 817 elementId = typeof elementId !== 'undefined' ? elementId : 'map'; 818 var sMapId = '#' + elementId, 819 sControl = typeof $(sMapId).data('control') !== 'undefined' ? String($(sMapId).data('control')) : ''; 820 sControl = sControl.trim(); 821 if (sControl !== '') { 822 sControl = sControl.toLowerCase(); 823 DDEAddAllControl(sControl); 824 } 825} 826 827/** 828 * Ajouter tous des controleurs à la carte 829 * 830 * @param sControl {string} : liste des controleurs séparés par "|" 831 */ 832function DDEAddAllControl(sControl) { 833 var isSecureContext = window.location.protocol == 'https:'; 834 var tControl = sControl.split('|'); 835 for (i = 0; i < tControl.length; i++) { 836 switch (tControl[i]) { 837 case 'attribution': 838 var OControAttribution = new ol.control.Attribution({ 839 target: controlConfig.attribution.target, 840 collapsible: controlConfig.attribution.collapsible, 841 collapsed: controlConfig.attribution.collapsed, 842 tipLabel: controlConfig.attribution.tipLabel, 843 label: controlConfig.attribution.label, 844 collapseLabel: controlConfig.attribution.collapseLabel, 845 }); 846 oMap.addControl(OControAttribution); 847 break; 848 case 'zoom': 849 var OControZoom = new ol.control.Zoom({ 850 zoomInTipLabel: controlConfig.zoom.zoomInTipLabel, 851 zoomOutTipLabel: controlConfig.zoom.zoomOutTipLabel, 852 target: controlConfig.zoom.target, 853 }); 854 oMap.addControl(OControZoom); 855 break; 856 case 'zoomslider': 857 var OControZoomSlider = new ol.control.ZoomSlider(); 858 oMap.addControl(OControZoomSlider); 859 break; 860 case 'fullscreen': 861 var OControFullScreen = new ol.control.FullScreen({ 862 tipLabel: controlConfig.fullscreen.tipLabel, 863 }); 864 oMap.addControl(OControFullScreen); 865 break; 866 case 'overviewmap': 867 var OControlOverviewMap = new ol.control.OverviewMap({ 868 className: controlConfig.overviewmap.className, 869 layers: [ 870 new ol.layer.Tile({ 871 source: new ol.source.OSM(), 872 }), 873 ], 874 collapseLabel: controlConfig.overviewmap.collapseLabel, 875 label: controlConfig.overviewmap.label, 876 collapsed: controlConfig.overviewmap.collapsed, 877 tipLabel: controlConfig.overviewmap.tipLabel, 878 target: controlConfig.overviewmap.target, 879 }); 880 oMap.addControl(OControlOverviewMap); 881 break; 882 case 'zoomtoextent': 883 var tExtent = getMapExtent(); 884 var zoomtoExtentIcon = document.createElement('span'); 885 zoomtoExtentIcon.innerHTML = controlConfig.zoomtoextent.innerHTML; 886 var OControlZoomToExtent = new ol.control.ZoomToExtent({ 887 tipLabel: controlConfig.zoomtoextent.tipLabel, 888 //label : controlConfig.zoomtoextent.label, 889 label: zoomtoExtentIcon, 890 extent: tExtent, 891 target: controlConfig.zoomtoextent.target, 892 }); 893 oMap.addControl(OControlZoomToExtent); 894 break; 895 case 'geolocation': 896 if (isSecureContext) { 897 addGeolocationControl(); 898 var OGeolocation = new app.GeolocationControl({ 899 target: controlConfig.geolocation.target, 900 }); 901 oMap.addControl(OGeolocation); 902 } 903 break; 904 case 'search': 905 addSearchControl(); 906 var OSearch = new app.SearchControl(controlConfig.search); 907 oMap.addControl(OSearch); 908 break; 909 case 'itinerary': 910 if (isSecureContext) { 911 addItineraryControl(); 912 var OItinerary = new app.ItineraryControl(controlConfig.itinerary); 913 oMap.addControl(OItinerary); 914 } 915 break; 916 } 917 } 918} 919 920/** 921 * Renvoi l'etendue de la carte (limites visible de la carte) 922 * 923 * @param string elementId: identifiant de l'élément du DOm qui va contenir la carte 924 * 925 *@return {array} 926 */ 927function getMapExtent(elementId) { 928 elementId = typeof elementId !== 'undefined' ? elementId : 'map'; 929 var sMapId = '#' + elementId, 930 tExtent; 931 if ( 932 typeof $(sMapId).data('minlon') !== 'undefined' && 933 typeof $(sMapId).data('minlat') !== 'undefined' && 934 typeof $(sMapId).data('maxlon') !== 'undefined' && 935 typeof $(sMapId).data('maxlat') !== 'undefined' 936 ) { 937 var nMinLon = parseFloat($(sMapId).data('minlon')); 938 var nMinLat = parseFloat($(sMapId).data('minlat')); 939 var nMaxLon = parseFloat($(sMapId).data('maxlon')); 940 var nMaxLat = parseFloat($(sMapId).data('maxlat')); 941 // Trasnformer extent vers EPSG:3857 942 tExtent = [nMinLon, nMinLat, nMaxLon, nMaxLat]; 943 tExtent = ol.extent.applyTransform(tExtent, ol.proj.getTransform('EPSG:4326', 'EPSG:3857')); 944 } 945 return tExtent; 946} 947 948/** 949 * Initialisation de l'arbre des calques 950 * 951 * @param {objet} map: ol.map 952 * @param {string} div: id du div qui va contenir l'arbre des calques 953 * @return {null} 954 */ 955function DDEInitLayerTree(map, div) { 956 var elem = DDEBuildLayerTree(map.getLayerGroup()); 957 $('#' + div) 958 .empty() 959 .append(elem); 960} 961 962/** 963 * Construit l'arbre des calques d'un calque 964 * 965 * @param {object} layer: layer 966 * @return {String} 967 */ 968function DDEBuildLayerTree(layer) { 969 var elem; 970 var name = layer.get('name') ? layer.get('name') : 'Couche sans nom'; 971 var label = layer.get('label') ? layer.get('label') : 'Couche sans label'; 972 var div = 973 '<li> <label for="' + 974 name + 975 '" class="checkbox form-check-input"> </span> <input type="checkbox" class="visible" id="' + 976 name + 977 '"> ' + 978 label +
979 ' </label>'; 980 if (layer.getLayers) { 981 var sublayersElem = ''; 982 var layers = layer.getLayers().getArray(), 983 len = layers.length; 984 for (var i = len - 1; i >= 0; i--) { 985 sublayersElem += DDEBuildLayerTree(layers[i]); 986 } 987 elem = div + ' <ul>' + sublayersElem + '</ul></li>'; 988 } else { 989 elem = div + ' </li>'; 990 } 991 return elem; 992} 993 994/** 995 * Relier les calques avec des cases a coches 996 * 997 * @param {objet} map: ol.map 998 * @return {null} 999 */ 1000function DDEBindLayersInputs(map) { 1001 var oRootLayerGroup = map.getLayerGroup(); 1002 var sName = oRootLayerGroup.get('name'); 1003 DDEBindInputs('#' + sName, oRootLayerGroup); 1004 var tLayers = map.getLayers().getArray(); 1005 tLayers.forEach(function (layer) { 1006 sName = layer.get('name'); 1007 DDEBindInputs('#' + sName, layer); 1008 if (layer instanceof ol.layer.Group) { 1009 layer.getLayers().forEach(function (sublayer, j) { 1010 sName = sublayer.get('name'); 1011 DDEBindInputs('#' + sName, sublayer); 1012 }); 1013 } 1014 }); 1015} 1016 1017/** 1018 * relier un calque a un input du dom 1019 * 1020 * @param {string} layerid: id de l'input 1021 * @param {objet} layer: layer 1022 */ 1023function DDEBindInputs(layerid, layer) { 1024 new ol.dom.Input($(layerid)[0]).bindTo('checked', layer, 'visible'); 1025} 1026 1027/** 1028 * Ajouter un calque à partir d'un fichier kml 1029 * 1030 * @param {object} option : les options du calque 1031 * {string} option.name: id du layer 1032 * {string} option.label: etiquette (affichage) du calque (layer) 1033 * {string} option.url: chemin vers le fichier kml 1034 * {integer} option.action: numero de l'action à executer (ajax) 1035 * {ol.style.Style} option.style: objet de style 1036 * {boolean} option.visibility: calque visible ou pas 1037 * {boolean} option.protection: calque protégé ou pas (visible uniquement en extranet) 1038 * {string} option.protectionContainerId : id du div contenant l'information si l'utlisateur est logge en extranet ou non 1039 * {float} option.opacity: opacitie du calque entre 0 et 1 1040 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1041 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1042 * {string} option.request : façon de récuperer les données (_GEOJSON, LOCAL) 1043 * {string} option.dataContainerId : id du div contenant les données si request == '_LOCAL' 1044 * {integer} option.order : ordre du calque 1045 * 1046 * @return void|null 1047 */ 1048function DDEAddLayerFromKml(option) { 1049 //cas de calque protegé 1050 var oProtectionElement = document.getElementById(option.protectionContainerId); 1051 if (option.protection === true && oProtectionElement !== null) { 1052 var sProtection = oProtectionElement.textContent; 1053 if (sProtection !== '1') { 1054 return null; 1055 } 1056 } 1057 1058 var oLayer = new ol.layer.Vector({ 1059 name: option.name, 1060 label: option.label, 1061 source: new ol.source.Vector({ 1062 url: option.url, 1063 format: new ol.format.KML({ 1064 extractStyles: false, 1065 }), 1066 }), 1067 style: option.style, 1068 visible: option.visibility, 1069 opacity: option.opacity, 1070 minResolution: option.minResolution, 1071 maxResolution: option.maxResolution, 1072 }); 1073 1074 addLayerToMap(oLayer, option.order); 1075} 1076 1077/** 1078 * Ajouter un calque à partir d'un fichier GeoJson 1079 * 1080 * @param {object} option : les options du calque 1081 * {string} option.name: id du layer 1082 * {string} option.label: etiquette (affichage) du calque (layer) 1083 * {string} option.url: chemin vers le fichier kml 1084 * {integer} option.action: numero de l'action à executer (ajax) 1085 * {ol.style.Style} option.style: objet de style 1086 * {boolean} option.visibility: calque visible ou pas 1087 * {boolean} option.protection: calque protégé ou pas (visible uniquement en extranet) 1088 * {string} option.protectionContainerId : id du div contenant l'information si l'utlisateur est logge en extranet ou non 1089 * {float} option.opacity: opacitie du calque entre 0 et 1 1090 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1091 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1092 * {string} option.request : façon de récuperer les données (_GEOJSON, LOCAL) 1093 * {string} option.dataContainerId : id du div contenant les données si request == '_LOCAL' 1094 * {integer} option.order : ordre du calque 1095 * {boolean} enableClustering : activer ou pas le clustering 1096 * {object} cluster : objet regroupant les options du clustering 1097 * 1098 * @return void|null 1099 */ 1100function DDEAddLayerFromGeoJson(option) { 1101 //cas de calque protegé 1102 var oProtectionElement = document.getElementById(option.protectionContainerId); 1103 if (option.protection === true && oProtectionElement !== null) { 1104 var sProtection = oProtectionElement.textContent; 1105 if (sProtection !== '1') { 1106 return null; 1107 } 1108 } 1109 1110 var sParam = option.url; 1111 if (option.action != '') { 1112 sParam += '?action=' + option.action; 1113 } 1114 if (option.protection === true) { 1115 sParam += '&protect=1'; 1116 } 1117 1118 //source standard 1119 var vectorSource = new ol.source.Vector({ 1120 url: sParam, 1121 format: new ol.format.GeoJSON(), 1122 });
1123 1124 var source = vectorSource, 1125 style = option.style; 1126 1127 //clustering 1128 if (typeof option.enableClustering !== 'undefined' && option.enableClustering === true) { 1129 var distance = typeof option.cluster.option.distance !== 'undefined' ? option.cluster.option.distance : 20, 1130 source = new ol.source.Cluster({ 1131 distance: distance, 1132 source: vectorSource, 1133 }); 1134 if (typeof option.cluster.style !== 'undefined') style = option.cluster.style; 1135 } 1136 1137 vectorSource.on('addfeature', function (event) { 1138 var feature = event.feature; 1139 // traitement affichage des recurrenes 1140 var recurrence = feature.get('recurrence_active'); 1141 if (recurrence) { 1142 if (!DDETestRecurrence(recurrence)) { 1143 vectorSource.removeFeature(feature); 1144 return null; 1145 } 1146 } 1147 1148 // blinking 1149 var blink = feature.get('clignot'); 1150 if (blink === true) { 1151 if (typeof timerBlinking === 'undefined') { 1152 timerBlinking = {}; 1153 } 1154 if (typeof blinkFeatureGeojson[option.name] === 'undefined') { 1155 blinkFeatureGeojson[option.name] = []; 1156 } 1157 1158 if (typeof timerBlinking[option.name] === 'undefined') { 1159 timerBlinking[option.name] = setInterval(function () { 1160 for (var i = 0; i < blinkFeatureGeojson[option.name].length; i++) { 1161 setBlinking(blinkFeatureGeojson[option.name][i]); 1162 } 1163 }, 1000); 1164 } 1165 blinkFeatureGeojson[option.name].push(feature); 1166 } 1167 }); 1168 1169 var oLayer = new ol.layer.Vector({ 1170 name: option.name, 1171 label: option.label, 1172 source: source, 1173 style: function (feature, resolution) { 1174 // Récupère le style de l'option 1175 var styleFeature = style(feature, resolution); 1176 1177 // Retourne vide si l'élément n'est pas visible 1178 if (feature.get('type') == 'CUSTOM_BARREAU' || feature.get('type') == 'CUSTOM_ZONE') { 1179 if (!feature.get('est_visible')) { 1180 return null; 1181 } 1182 } 1183 1184 return styleFeature; 1185 }, 1186 visible: option.visibility, 1187 opacity: option.opacity, 1188 minResolution: option.minResolution, 1189 maxResolution: option.maxResolution, 1190 }); 1191 1192 addLayerToMap(oLayer, option.order); 1193} 1194 1195/** 1196 * Mis à jour un calque à partir d'un fichier GeoJson 1197 * 1198 * @param {string} layerName : nom du calque à mettre à jour 1199 * 1200 * @return boolean 1201 */ 1202function DDEUpdateLayerFromGeoJson(layerName) { 1203 var vectorLayer = getLayerByName(layerName); 1204 if (vectorLayer === null) return false; 1205 1206 var url = vectorLayer.getSource().getUrl(), 1207 source = new ol.source.Vector({ 1208 url: url, 1209 format: new ol.format.GeoJSON(), 1210 }); 1211 //mise à jour de la source 1212 vectorLayer.setSource(source); 1213 1214 return true; 1215} 1216 1217/** 1218 * Ajouter un calque à partir d'un GeoJson sous format texte 1219 * 1220 * @param {string} text: données GeoJson sous format texte 1221 * @param {object} option : les options du calque 1222 * {string} option.name: id du layer 1223 * {string} option.label: etiquette (affichage) du calque (layer) 1224 * {string} option.url: chemin vers le fichier kml 1225 * {integer} option.action: numero de l'action à executer (ajax) 1226 * {ol.style.Style} option.style: objet de style 1227 * {boolean} option.visibility: calque visible ou pas 1228 * {boolean} option.protection: calque protégé ou pas (visible uniquement en extranet) 1229 * {string} option.protectionContainerId : id du div contenant l'information si l'utlisateur est logge en extranet ou non 1230 * {float} option.opacity: opacitie du calque entre 0 et 1 1231 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1232 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1233 * {string} option.request : façon de récuperer les données (_GEOJSON, LOCAL) 1234 * {string} option.dataContainerId : id du div contenant les données si request == '_LOCAL' 1235 * {integer} option.order : ordre du calque 1236 * 1237 * @return void|null 1238 */ 1239function DDEAddLayerFromGeoJsonText(text, option) { 1240 //cas de calque protegé 1241 var oProtectionElement = document.getElementById(option.protectionContainerId); 1242 if (option.protection === true && oProtectionElement !== null) { 1243 var sProtection = oProtectionElement.textContent; 1244 if (sProtection !== '1') { 1245 return null; 1246 } 1247 } 1248 1249 //creation des features 1250 var geojsonFormat = new ol.format.GeoJSON(); 1251 var features = geojsonFormat.readFeatures(text, { featureProjection: defaultOsmProjection }); 1252 1253 var oLayer = new ol.layer.Vector({ 1254 name: option.name, 1255 label: option.label, 1256 source: new ol.source.Vector({ 1257 features: features, 1258 format: new ol.format.GeoJSON({ 1259 defaultDataProjection: defaultOsmProjection, 1260 }), 1261 }), 1262 style: option.style, 1263 visible: option.visibility, 1264 opacity: option.opacity, 1265 minResolution: option.minResolution, 1266 maxResolution: option.maxResolution, 1267 });
1268 1269 addLayerToMap(oLayer, option.order); 1270} 1271 1272/** 1273 * Ajoute un calque spécial à la carte (calque ayant besoin de traitement suplémentaire des données) 1274 * 1275 * @param option : les options du calque spécial 1276 * {string} option.name: id du layer 1277 * {string} option.label: etiquette (affichage) du calque (layer) 1278 * {string} option.url: chemin vers le fichier kml 1279 * {integer} option.action: numero de l'action à executer (ajax) 1280 * {ol.style.Style} option.style: objet de style 1281 * {boolean} option.visibility: calque visible ou pas 1282 * {boolean} option.protection: calque protégé ou pas (visible uniquement en extranet) 1283 * {string} option.protectionContainerId : id du div contenant l'information si l'utlisateur est logge en extranet ou non 1284 * {float} option.opacity: opacitie du calque entre 0 et 1 1285 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1286 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1287 * {string} option.request : façon de récuperer les données (_GEOJSON, LOCAL) 1288 * {string} option.dataContainerId : id du div contenant les données si request == '_LOCAL' 1289 * {integer} option.order : ordre du calque 1290 * 1291 * @return void|null 1292 */ 1293function DDEAddSpecialLayer(option) { 1294 //cas de calque protegé 1295 var oProtectionElement = document.getElementById(option.protectionContainerId); 1296 if (option.protection === true && oProtectionElement !== null) { 1297 var sProtection = oProtectionElement.textContent; 1298 if (sProtection !== '1') { 1299 return null; 1300 } 1301 } 1302 1303 if (option.request === '_GEOJSON') { 1304 var oParam = { action: option.action }; 1305 if (option.protection === true) { 1306 oParam.protect = '1'; 1307 } 1308 if (option.date !== undefined && option.date !== '') { 1309 oParam.date = option.date; 1310 } 1311 1312 var drawLayer = function (optionLayer) { 1313 var cloneOption = $.extend({}, optionLayer); 1314 return function (layerData) { 1315 var tFeature = renderDataAsLayer(layerData, cloneOption); 1316 1317 if ( 1318 tFeature !== null && 1319 cloneOption.featureDisplayContainerId !== undefined && 1320 cloneOption.featureDisplayContainerId !== '' 1321 ) { 1322 displayFeaturesInHtmlTable(tFeature, cloneOption.featureDisplayContainerId); 1323 } 1324 }; 1325 }; 1326 1327 $.ajax({
1328 type: 'GET', 1329 url: option.url, 1330 async: true, 1331 data: oParam, 1332 dataType: 'json', 1333 }) 1334 .done(drawLayer(option)) 1335 .fail(function () { 1336 return null; 1337 }); 1338 } else if (option.request === '_LOCAL' && option.dataContainerId !== '') { 1339 var oElement = document.getElementById(option.dataContainerId); 1340 if (oElement !== null) { 1341 var data = null; 1342 try { 1343 data = JSON.parse(oElement.textContent); 1344 renderDataAsLayer(data, option); 1345 } catch (e) {} 1346 } 1347 } else { 1348 return null; 1349 } 1350} 1351 1352/** 1353 * Traiter les données et les ajouter à la carte sous format d'un calque 1354 * 1355 * @param {object} data : données sous format GeoJson 1356 * @param {object} option : les options des données 1357 * {string} option.name: id du layer 1358 * {string} option.label: etiquette (affichage) du calque (layer) 1359 * {ol.style.Style} option.style: objet de style 1360 * {boolean} option.visibility: calque visible ou pas 1361 * {float} option.opacity: opacitie du calque entre 0 et 1 1362 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1363 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1364 * {integer} option.order : ordre du calque 1365 * 1366 * @return feature|null 1367 */ 1368function renderDataAsLayer(data, option) { 1369 if ( 1370 typeof data !== 'undefined' && 1371 data !== null && 1372 typeof data.features !== 'undefined' && 1373 data.features.length > 0 1374 ) { 1375 var sGeometry = data.features[0].geometry.type; 1376 var oGeoJson = new ol.format.GeoJSON({ 1377 defaultDataProjection: defaultDataProjection, 1378 geometryName: sGeometry, 1379 }); 1380 var tFeature = oGeoJson.readFeatures(data, { 1381 dataProjection: defaultDataProjection, 1382 featureProjection: defaultOsmProjection, 1383 }); 1384 1385 if (typeof option.sublayer !== 'undefined' && option.sublayer.length > 0) { 1386 //cas de sous calque 1387 DDEAddSubLayer(option.sublayer, tFeature); 1388 } else { 1389 //ajout d'un seul calque 1390 DDEAddVictorLayer(tFeature, option); 1391 } 1392 1393 return tFeature; 1394 } else { 1395 return null; 1396 } 1397} 1398 1399/** 1400 * Ajouter plusieurs sous calques 1401 * 1402 * @param {json{}} config : configuration des sous calques 1403 * @param {ol.Feature[]} features : tableau de caracteristiques 1404 * 1405 * @return void 1406 */ 1407function DDEAddSubLayer(config, features) { 1408 var oConfig = {}; 1409 var oFeature = {}; 1410 1411 //initialisation de la matrice 1412 var tFeature = [[]]; 1413 for (var l = 0; l < config.length; l++) { 1414 tFeature[l] = []; 1415 } 1416 1417 var bFind = true; 1418 for (var i = 0; i < features.length; i++) { 1419 // Vérifie si l'élément fait partie d'un calques 1420 bFind = false; 1421 oFeature = features[i]; 1422 for (var j = 0; j < config.length; j++) { 1423 // Vérifie si le code de l'élément correspond à ceux du calque 1424 oConfig = config[j]; 1425 for (var k = 0; k < oConfig.code.length; k++) { 1426 // verifie si besoin d'executer une fonctioin spécifique couche-feature 1427 if (typeof oConfig.afterLoadFunction !== 'undefined') { 1428 oConfig.afterLoadFunction(oFeature); 1429 } 1430 1431 if (oFeature.get('code') == oConfig.code[k]) { 1432 tFeature[j].push(oFeature); 1433 bFind = true; 1434 break; 1435 } 1436 } 1437 1438 if (bFind) { 1439 break; 1440 } 1441 } 1442 } 1443 1444 //ajout des calques 1445 for (l = 0; l < config.length; l++) { 1446 DDEAddVictorLayer(tFeature[l], config[l]); 1447 } 1448} 1449 1450/** 1451 * Ajoute ou mis à jour un calque vectoriel à la carte 1452 * 1453 * @param {ol.Feature[]} features : tableau de caracteristiques 1454 * @param {object} option : options du calque 1455 * {string} option.name: id du layer 1456 * {string} option.label: etiquette (affichage) du calque (layer) 1457 * {ol.style.Style} option.style: objet de style 1458 * {boolean} option.visibility: calque visible ou pas 1459 * {float} option.opacity: opacité du calque entre 0 et 1 1460 * {float} option.minResolution : resolution minimale au-dessus de laquelle le calque est visible 1461 * {float} option.maxResolution : resolution maximale au-dessous de laquelle le calque est visible 1462 * {integer} option.order : ordre du calque 1463 * 1464 * @return void 1465 */ 1466function DDEAddVictorLayer(tFeature, option) { 1467 // creation du calque 1468 var isCluster = false; 1469 var vectorLayer = getLayerByName(option.name); 1470 var createLayer = vectorLayer === null ? true : false; 1471 var vectorSource = new ol.source.Vector({ 1472 projection: defaultOsmProjection, 1473 });
1474 vectorSource.addFeatures(tFeature); 1475 // Ajoute les pictos des barreaux 1476 if (option.name.substring(0, 13) == 'layer-barreau') { 1477 var data = { 1478 type: 'FeatureCollection', 1479 features: [], 1480 }; 1481 1482 for (var i = 0; i < tFeature.length; i++) { 1483 tFeature[i].set('layername', option.name); 1484 1485 // Récupère les pictos 1486 var feature = tFeature[i]; 1487 var pictos = feature.get('pictos'); 1488 1489 if (typeof pictos != 'undefined') { 1490 for (var j = 0; j < pictos.length; j++) { 1491 var picto = pictos[j]; 1492 1493 if (picto.visibility == 'AU_SURVOL' || picto.visibility == 'TOUJOURS') { 1494 var scaling = -1; 1495 if (picto.visibility == 'TOUJOURS') { 1496 scaling = picto.icon_scale; 1497 } 1498 1499 var hasBlinking = false; 1500 if (picto.blinking == '_T') { 1501 hasBlinking = true; 1502 } 1503 1504 // Crée le picto pour la carte 1505 var pictoFeature = { 1506 type: 'Feature', 1507 id: 'barreau_picto_' + picto.id_repere, 1508 geometry: { 1509 type: 'Point', 1510 coordinates: picto.geometry.coordinates, 1511 }, 1512 properties: { 1513 id: 'barreau_picto_' + picto.id_repere, 1514 url_icone: picto.icon_url, 1515 echelle: scaling, 1516 icon_scale: picto.icon_scale, 1517 visibility: picto.visibility, 1518 clignot: hasBlinking, 1519 nopopup: true, 1520 zIndex: 9999999999, 1521 visibility: picto.visibility, 1522 }, 1523 }; 1524 1525 // Ajoute le picto à la liste 1526 data.features.push(pictoFeature); 1527 } 1528 } 1529 } 1530 } 1531 1532 // Ajoute les pictos à la carte 1533 var geojson = new ol.format.GeoJSON({ 1534 defaultDataProjection: defaultDataProjection, 1535 geometryName: 'Point', 1536 }); 1537 var newFeatures = geojson.readFeatures(data, { 1538 dataProjection: defaultDataProjection, 1539 featureProjection: defaultOsmProjection, 1540 }); 1541 vectorSource.addFeatures(newFeatures); 1542 } 1543 1544 if (typeof option.enableClustering !== 'undefined' && option.enableClustering === true) { 1545 //clustering 1546 isCluster = true; 1547 1548 var distance = typeof option.cluster.option.distance !== 'undefined' ? option.cluster.option.distance : 20; 1549 var clusterSource = new ol.source.Cluster({ 1550 distance: distance, 1551 source: vectorSource, 1552 }); 1553 1554 // Remet à zéro le clignotement des repères en cluster 1555 // Le code responsable de ça se trouve dans script-config.js 1556 if (typeof clusterTimerBlinking !== 'undefined') { 1557 // Récupère les codes du layer 1558 var layerCodeList = String(option.code); 1559 var layerCodes = layerCodeList.split(','); 1560 1561 // Remet à zéro le clignotement de chaque code de la couche 1562 for (var i = 0; i < layerCodes.length; i++) { 1563 if ( 1564 typeof clusterTimerBlinking[layerCodes[i]] !== 'undefined' && 1565 typeof clusterTimerBlinking[layerCodes[i]].timer === 'number' 1566 ) { 1567 clearInterval(clusterTimerBlinking[layerCodes[i]].timer); 1568 clusterTimerBlinking[layerCodes[i]] = undefined; 1569 } 1570 } 1571 } 1572 1573 if (createLayer) { 1574 vectorLayer = new ol.layer.Vector({ 1575 name: option.name, 1576 label: option.label, 1577 source: clusterSource, 1578 style: option.cluster.style, 1579 visible: option.visibility, 1580 opacity: option.opacity, 1581 minResolution: option.minResolution, 1582 maxResolution: option.maxResolution, 1583 }); 1584 } else { 1585 vectorLayer.getSource().clear(); 1586 vectorLayer.setSource(clusterSource); 1587 } 1588 } else { 1589 if (createLayer) { 1590 vectorLayer = new ol.layer.Vector({ 1591 name: option.name, 1592 label: option.label, 1593 source: vectorSource, 1594 style: function (feature, resolution) { 1595 // Récupère le style de l'option 1596 var style = option.style(feature, resolution); 1597 1598 // Redéfinit le zIndex de l'élément s'il est définit 1599 if (feature.get('zIndex')) { 1600 for (var i = 0; i < style.length; i++) { 1601 style[i].setZIndex(feature.get('zIndex')); 1602 } 1603 } 1604 1605 return style; 1606 }, 1607 visible: option.visibility, 1608 opacity: option.opacity, 1609 minResolution: option.minResolution, 1610 maxResolution: option.maxResolution, 1611 }); 1612 } else { 1613 //mise à jour d'un calque existant 1614 vectorLayer.getSource().clear(); 1615 vectorLayer.setSource(vectorSource); 1616 } 1617 } 1618 1619 //ajout du calque a la carte 1620 if (createLayer) { 1621 addLayerToMap(vectorLayer, option.order); 1622 } 1623 1624 //cas des evenements clignotants et recurrents 1625 if (!isCluster) { 1626 var blinkFeature = []; 1627 vectorSource.forEachFeature(function (feature) { 1628 // evenements recurrents 1629 var recurrence = feature.get('recurrence_active'); 1630 if (recurrence) { 1631 if (!DDETestRecurrence(recurrence)) {
1632 vectorSource.removeFeature(feature); 1633 } 1634 } 1635 1636 // evenements clignotants 1637 var blink = feature.get('clignot'); 1638 if (blink) { 1639 blinkFeature.push(feature); 1640 } 1641 }); 1642 1643 if (typeof timerBlinking !== 'undefined' && typeof timerBlinking[option.name] === 'number') { 1644 clearInterval(timerBlinking[option.name]); 1645 timerBlinking[option.name] = undefined; 1646 } 1647 1648 if (blinkFeature.length !== 0) { 1649 if (typeof timerBlinking === 'undefined') { 1650 timerBlinking = {}; 1651 } 1652 timerBlinking[option.name] = setInterval(function () { 1653 for (var i = 0; i < blinkFeature.length; i++) { 1654 setBlinking(blinkFeature[i]); 1655 } 1656 }, 1000); 1657 } 1658 } 1659} 1660 1661/** 1662 * retourne le message du PMV 1663 * 1664 * @param {object} attributes : objet des proprietes 1665 * 1666 * @return {string[]} 1667 */ 1668function getPmvMessage(attributes) { 1669 var tLigne = [ 1670 [attributes.ligne0_0, attributes.ligne0_1], 1671 [attributes.ligne1_0, attributes.ligne1_1], 1672 [attributes.ligne2_0, attributes.ligne2_1], 1673 [attributes.ligne3_0, attributes.ligne3_1], 1674 ]; 1675 var sDateRegExp = new RegExp('^[ ]*[+]?DT[0-9]{1}[ ]*$'); 1676 var sTimeRegExp = new RegExp('^[ ]*[+]?HR[0-9]{1}[ ]*$'); 1677 var date = new Date(); 1678 var sHtml = ['', '']; 1679 for (var i = 0; i <= 3; i++) { 1680 for (var j = 0; j <= 1; j++) { 1681 if (tLigne[i][j] !== '') { 1682 if (sDateRegExp.test(tLigne[i][j])) { 1683 sHtml[j] += formaterDate(date); 1684 } else if (sTimeRegExp.test(tLigne[i][j])) { 1685 sHtml[j] += formaterHeure(date); 1686 } else { 1687 sHtml[j] += tLigne[i][j]; 1688 } 1689 1690 sHtml[j] += '<br/>'; 1691 } 1692 } 1693 } 1694 1695 return sHtml; 1696} 1697 1698/** 1699 * Formater la date sous le format jj/mm/aa 1700 * 1701 * @param {object} d : date 1702 * 1703 * @return {string} 1704 */ 1705function formaterDate(d) { 1706 var month = d.getMonth(); 1707 var day = d.getDate(); 1708 var year = d.getFullYear(); 1709 1710 //annee 1711 year = year.toString().substr(2, 2); 1712 1713 //mois
1714 month = month + 1; 1715 month = month + ''; 1716 if (month.length == 1) { 1717 month = '0' + month; 1718 } 1719 1720 //jour 1721 day = day + ''; 1722 if (day.length == 1) { 1723 day = '0' + day; 1724 } 1725 1726 return day + '/' + month + '/' + year; 1727} 1728 1729/** 1730 * Formater l'heure sous le format HH:MM 1731 * 1732 * @param {object} d : date 1733 * 1734 * @return {string} 1735 */ 1736function formaterHeure(d) { 1737 var minute = d.getMinutes(); 1738 var hour = d.getHours(); 1739 1740 //heure 1741 hour = hour + ''; 1742 if (hour.length == 1) { 1743 hour = '0' + hour; 1744 } 1745 1746 //minute 1747 minute = minute + ''; 1748 if (minute.length == 1) { 1749 minute = '0' + minute; 1750 } 1751 1752 return hour + ':' + minute; 1753} 1754 1755/** 1756 * Initialisation de l'affichage des popup et creation d'un calque overlay qui va contenir les popups 1757 * 1758 * @param {string} divId : identifiant de la DIv contenant le popup 1759 * @param {string} elementId : base de l'identifiant des éléments de la popup 1760 * @param {boolean} autoPan : activer ou pas l'ajustement de la carte pour afficher l'intégralité du popup 1761 * 1762 * @return {object} { 1763 * 'overlay' : ol.Overlay, 1764 * 'title' : document.getElementById(elementId+'-title'), 1765 * 'content' : document.getElementById(elementId+'-content') 1766 * } 1767 */ 1768function initializePopUp(divId, elementId, autoPan) { 1769 //Ajout du la div du popup en cas de non existance 1770 if ($('#' + divId).length === 0) { 1771 var newdiv = document.createElement('div'); 1772 newdiv.setAttribute('id', divId); 1773 newdiv.setAttribute('class', 'ol-popup'); 1774 newdiv.innerHTML = 1775 '<a href="#" id="' + 1776 elementId + 1777 '-closer" class="ol-popup-closer"></a> <h3 id="' + 1778 elementId + 1779 '-title" class="popover-title"></h3> <div id="' + 1780 elementId + 1781 '-content" class="popover-content"></div>'; 1782 var parentDiv = document.getElementsByClassName('hiddenData')[0]; 1783 parentDiv.appendChild(newdiv); 1784 } 1785 1786 var container = document.getElementById(divId); 1787 1788 //bouton close 1789 var closer = document.getElementById(elementId + '-closer'); 1790 closer.onclick = function () { 1791 overlay.setPosition(undefined); 1792 closer.blur(); 1793 return false; 1794 }; 1795 1796 //overlay 1797 var overlay = new ol.Overlay({ 1798 id: divId, 1799 element: container, 1800 autoPan: autoPan, 1801 stopEvent: true, 1802 autoPanAnimation: { 1803 duration: 250, 1804 }, 1805 }); 1806 1807 //ajout de l'ovelay a la carte 1808 oMap.addOverlay(overlay); 1809 1810 return { 1811 overlay: overlay, 1812 title: document.getElementById(elementId + '-title'), 1813 content: document.getElementById(elementId + '-content'), 1814 }; 1815} 1816 1817function renderBarreauPictos(evt) { 1818 // Récupère la fonctionnalité 1819 var feature = oMap.forEachFeatureAtPixel( 1820 evt.pixel, 1821 function (feature, layer) { 1822 return DDEFeatureFilter(feature, layer); 1823 }, 1824 null, 1825 function (layer) { 1826 return DDELayerFilter(layer); 1827 } 1828 ); 1829 1830 // Retourne si aucune fonctionnalité 1831 if (!feature) { 1832 for (var i = 0; i < pictoHoverFeatures.length; i++) { 1833 var properties = pictoHoverFeatures[i].getProperties(); 1834 properties.echelle = -1; 1835 pictoHoverFeatures[i].setProperties(properties); 1836 } 1837 pictoHoverFeatures = []; 1838 1839 for (var i = 0; i < barreauHoverFeatures.length; i++) { 1840 var properties = barreauHoverFeatures[i].getProperties(); 1841 properties.est_visible = 0; 1842 barreauHoverFeatures[i].setProperties(properties); 1843 } 1844 barreauHoverFeatures = []; 1845 1846 for (var i = 0; i < zoneHoverFeatures.length; i++) { 1847 var properties = zoneHoverFeatures[i].getProperties(); 1848 properties.est_visible = 0; 1849 zoneHoverFeatures[i].setProperties(properties); 1850 } 1851 zoneHoverFeatures = []; 1852 1853 // Retourne 1854 return false; 1855 } 1856 1857 properties = feature.getProperties(); 1858 1859 if (feature.get('type') == '_BARREAU') { 1860 var pictos = feature.get('pictos'); 1861 var layername = feature.get('layername'); 1862 1863 if (typeof pictos != 'undefined') { 1864 for (var i = 0; i < pictos.length; i++) { 1865 var picto = pictos[i]; 1866 1867 if (picto.visibility == 'AU_SURVOL') { 1868 // Récupère l'élément 1869 pictoFeature = getLayerFeatureById(layername, 'barreau_picto_' + picto.id_repere); 1870 1871 var properties = pictoFeature.getProperties(); 1872 properties.echelle = properties.icon_scale; 1873 pictoFeature.setProperties(properties); 1874 1875 pictoHoverFeatures.push(pictoFeature); 1876 } 1877 } 1878 } 1879 } else if ( 1880 feature.get('type') == 'CUSTOM_PICTO' || 1881 feature.get('type') == 'CUSTOM_BARREAU' || 1882 feature.get('type') == 'CUSTOM_ZONE' 1883 ) { 1884 var pictos = feature.get('pictos') ?? []; 1885 var barreaux = feature.get('barreaux') ?? []; 1886 var zones = feature.get('zones') ?? []; 1887 var layername = 'layer-custom'; 1888 1889 for (var i = 0; i < pictos.length; i++) { 1890 var pictoId = pictos[i]; 1891 1892 // Récupère l'élément 1893 pictoFeature = getLayerFeatureById(layername, pictoId); 1894 1895 if (pictoFeature.get('visibility') == 'AU_SURVOL') { 1896 var properties = pictoFeature.getProperties(); 1897 properties.echelle = properties.icon_scale; 1898 pictoFeature.setProperties(properties); 1899 1900 pictoHoverFeatures.push(pictoFeature); 1901 } 1902 } 1903 1904 for (var i = 0; i < barreaux.length; i++) { 1905 var barreauId = barreaux[i]; 1906 1907 // Récupère l'élément 1908 barreauFeature = getLayerFeatureById(layername, barreauId); 1909 1910 if (barreauFeature.get('visibility') == 'AU_SURVOL') { 1911 var properties = barreauFeature.getProperties(); 1912 properties.est_visible = 1; 1913 barreauFeature.setProperties(properties); 1914 1915 barreauHoverFeatures.push(barreauFeature); 1916 } 1917 } 1918 1919 for (var i = 0; i < zones.length; i++) { 1920 var zoneId = zones[i]; 1921 1922 // Récupère l'élément 1923 zoneFeature = getLayerFeatureById(layername, zoneId); 1924 1925 if (zoneFeature.get('visibility') == 'AU_SURVOL') { 1926 var properties = zoneFeature.getProperties(); 1927 properties.est_visible = 1; 1928 zoneFeature.setProperties(properties); 1929 1930 zoneHoverFeatures.push(zoneFeature); 1931 } 1932 } 1933 } 1934} 1935/** 1936 *@returns {Boolean} : currentOnglet 1937 */ 1938function getCurrentOnglet(){
1939 let currentOnglet; 1940 $('.NavigationTab li a').each(function() { 1941 if ($(this).attr('aria-selected') === 'true') { 1942 currentOnglet = $(this).attr('aria-controls'); 1943 return ; 1944 } 1945 }); 1946 return currentOnglet 1947 1948} 1949 1950/** 1951 * Afficher le popup lié à l'élément evt sur le calque overlay avec le titre le content du popup 1952 * 1953 * @param evt {object} evt : événement relier au clique de souris sur la carte (ol.MapBrowserPointerEvent) 1954 * @param overlay {object} : calque overlay (ol.overlay) 1955 * @param title {string} : titre du popup 1956 * @param content {string} : corps du popup 1957 * @param showPopup {boolean} : afficher ou pas le popup 1958 * @param otherOverlay {object[]} : les autres calques overlay (ol.overlay) 1959 1960 * @returns {Boolean} : affichage ou non du popup 1961 */ 1962function renderPopUp(evt, overlay, title, content, showPopup, otherOverlay) { 1963 $('.NavigationTab li a').each(function() { 1964 $(this).click(function(e) { 1965 overlay.setPosition(undefined); 1966 }) 1967 }); 1968 // Retourne directement si on affiche pas le popup 1969 if (!showPopup) { 1970 return false; 1971 } 1972 1973 // Remet à zéro le minuteur des webcams 1974 if (typeof timer === 'number') { 1975 clearInterval(timer); 1976 timer = undefined; 1977 overlay.setPosition(undefined); 1978 } 1979 1980 // Ferme l'autre overlay 1981 if (otherOverlay instanceof ol.Overlay) { 1982 otherOverlay.setPosition(undefined); 1983 } 1984 1985 // Récupère la fonctionnalité 1986 var feature = oMap.forEachFeatureAtPixel( 1987 evt.pixel, 1988 function (feature, layer) { 1989 return DDEFeatureFilter(feature, layer); 1990 }, 1991 null, 1992 function (layer) { 1993 return DDELayerFilter(layer); 1994 } 1995 ); 1996 1997 // Retourne si aucune fonctionnalité 1998 if (!feature) { 1999 // Ferme l'overlay et le popup 2000 overlay.setPosition(undefined); 2001 2002 // Retourne 2003 return false; 2004 } 2005 2006 // Récupère le type de fonctionnalité 2007 var sType = feature.get('type'); 2008 2009 // Cas des liens sans popup 2010 if (sType === '_LIEN' && feature.get('affich_popup') === '_F') { 2011 if (evt.type === 'singleclick') { 2012 // Ferme l'overlay et ouvre l'url 2013 var sUrl = feature.get('link'); 2014 overlay.setPosition(undefined); 2015 window.open(sUrl, '_blank'); 2016 } 2017 2018 // Retourne 2019 return false; 2020 } 2021 2022 // Actualise le contenu et le titre 2023 var sTemplateTitre = getTemplateOfPopup(sType + '_TITRE', '_TITRE'); 2024 var sTitre = Mustache.render(sTemplateTitre, feature.getProperties()); 2025 var sTemplateCorps = getTemplateOfPopup(sType, '_CORPS'); 2026 var sCorps = ''; 2027 var oProperties = feature.getProperties(); 2028 2029 // Récupère les propriétés définies pour le site (si la fonction existe) 2030 // La fonction est déclarée pour le moment dans script-config.js 2031 if (typeof getPopupCustomExtraProperties === 'function') { 2032 // Récupère les propriétés 2033 var extraProperties = getPopupCustomExtraProperties(oProperties); 2034 2035 // Ajoute ou remplace les propriétés 2036 for (var key in extraProperties) { 2037 oProperties.key = extraProperties[key]; 2038 } 2039 } 2040 2041 // Récupère le contenu du popup selon le type 2042 switch (sType) { 2043 case '_PMV': 2044 var tMessage = getPmvMessage(oProperties); 2045 oProperties.message0 = tMessage[0]; 2046 oProperties.message1 = tMessage[1]; 2047 sCorps = Mustache.render(sTemplateCorps, oProperties); 2048 break; 2049 2050 case '_WEBCAM': 2051 case '_WEBCAM_VIDEO': 2052 if (oProperties.type_media == 'DEFILEMENT_IMAGE') { 2053 sTemplateCorps = getTemplateOfPopup('_WEBCAM_DEFILEMENT', '_CORPS'); 2054 } else if (oProperties.config == 'stream') { 2055 sTemplateCorps = getTemplateOfPopup('_WEBCAM_STREAM', '_CORPS'); 2056 } else if (oProperties.config == 'animation') {
2057 sTemplateCorps = getTemplateOfPopup('_WEBCAM_ANIMATION', '_CORPS'); 2058 } else { 2059 sTemplateCorps = getTemplateOfPopup(sType, '_CORPS'); 2060 } 2061 2062 var sIdWebcam = 'id="webcam_image_' + evt.type + '"', 2063 sWebcamTemplateCorps = sTemplateCorps.replace('id="webcam_image"', sIdWebcam); 2064 sCorps = Mustache.render(sWebcamTemplateCorps, oProperties); 2065 break; 2066 2067 default: 2068 sCorps = Mustache.render(sTemplateCorps, oProperties); 2069 break; 2070 } 2071 title.innerHTML = sTitre; 2072 content.innerHTML = sCorps; 2073 2074 // Positionne l'overlay 2075 var coord = evt.coordinate; 2076 var geometry = feature.getGeometry(); 2077 if (geometry instanceof ol.geom.Point) { 2078 coord = geometry.getCoordinates(); 2079 } 2080 overlay.setPosition(coord); 2081 2082 // Rafraichie l'image de la webcam 2083 if (sType.substring(0, 7) === '_WEBCAM') { 2084 // mets en place le caroussel 2085 $(document).ready(function () { 2086 var owl = $('.owl-carousel'); 2087 // teste si le pluging owlcarousel est chargé 2088 if (owl.length > 0 && typeof owl.owlCarousel === 'function') { 2089 owl.owlCarousel({ 2090 rtl: true, 2091 margin: 0, 2092 nav: true, 2093 loop: true, 2094 items: 1, 2095 }); 2096 } 2097 }); 2098 2099 // Récupère le délai 2100 var sDelai = oProperties.delai_rafraichissement || '1000'; 2101 var nDelai = parseFloat(sDelai); 2102 2103 // Rafraichie l'image 2104 var bRefreshWebcam = DDERefreshWebcamFeature(feature, evt.type); 2105 // Met en place la mise à jour de l'image 2106 if (bRefreshWebcam === true) { 2107 timer = setInterval(DDERefreshWebcamFeature, nDelai, feature, evt.type); 2108 } 2109 } 2110 2111 // Gérer l'affichage des déviations 2112 if (sType === '_DEVIATION') { 2113 //Si le mode d'affichage de déviation par onglet est activé 2114 if($('button.popupAction[data-onglet]').length){ 2115 let deviations = [{ selector: '#divDeviationPL', type: 'DEVIATION_PL' },{ selector: '#divDeviationVL', type: 'DEVIATION_VL' }]; 2116 let currentOnglet = getCurrentOnglet(); 2117 for (let i = deviations.length - 1; i >= 0; i--) { 2118 let onglets = []; 2119 if ($(deviations[i].selector).length > 0) { 2120 onglets = $(deviations[i].selector).attr('data-onglet').split(',') 2121 } 2122 if (!onglets.includes(currentOnglet)) { 2123 $('#popup_pointermove '+deviations[i].selector).hide(); 2124 $('#popup '+deviations[i].selector).hide(); 2125 } 2126 } 2127 } 2128 //mode d'affichage de déviation par onglet n'est pas activé 2129 $('button.popupAction:not([data-onglet])').click(function () { 2130 var sDeviations = $(this).attr('data-idsdeviations'); 2131 var aDeviations = sDeviations.split(','); 2132 2133 // Afficher la déviation 2134 manageDeviationsDisplay(aDeviations, true); 2135 overlay.setPosition(undefined); 2136 2137 var hideDeviation = function (evt) { 2138 if (evt.dragging) return; 2139 2140 var pixel = oMap.getEventPixel(evt.originalEvent); 2141 var hit = oMap.forEachFeatureAtPixel( 2142 pixel, 2143 function (feature, layer) { 2144 if (layer.get('name') == 'layer-deviation') { 2145 return true; 2146 } 2147 return false; 2148 }, 2149 null 2150 ); 2151 2152 // Si n'y a pas d'intersection avec avec un élément 2153 if (!hit) { 2154 // Masquer la déviation 2155 manageDeviationsDisplay(aDeviations, false); 2156 // Retirer l'event pour éviter de le cumuler à chaque fois qu'on clique pour voir la déviation 2157 oMap.un('singleclick', hideDeviation); 2158 } 2159 }; 2160 // Event pour gerer la déselection de la déviation 2161 oMap.on('singleclick', hideDeviation); 2162 }); 2163 2164 //Mode d'affichage de déviation par onglet est activé 2165 $('button.popupAction[data-onglet]').click(function () { 2166 var sDeviations = $(this).attr('data-idsdeviations'); 2167 var aDeviations = sDeviations.split(','); 2168 // Afficher la déviation 2169 manageDeviationsDisplayByOnglet(aDeviations, true); 2170 overlay.setPosition(undefined); 2171 2172 2173 var hideDeviation = function (evt) { 2174 if (evt.dragging) return; 2175 2176 var pixel = oMap.getEventPixel(evt.originalEvent);
2177 var hit = oMap.forEachFeatureAtPixel( 2178 pixel, 2179 function (feature, layer) { 2180 if (layer.get('name') == 'layer-deviation') { 2181 return true; 2182 } 2183 return false; 2184 }, 2185 null 2186 ); 2187 2188 // Si n'y a pas d'intersection avec avec un élément 2189 if (!hit) { 2190 // Masquer la déviation 2191 manageDeviationsDisplayByOnglet(aDeviations, false); 2192 // Retirer l'event pour éviter de le cumuler à chaque fois qu'on clique pour voir la déviation 2193 oMap.un('singleclick', hideDeviation); 2194 } 2195 }; 2196 // Event pour gerer la déselection de la déviation 2197 oMap.on('singleclick', hideDeviation); 2198 2199 $('.NavigationTab li a').each(function() { 2200 $(this).click(function(e) { 2201 manageDeviationsDisplayByOnglet(aDeviations, false); 2202 overlay.setPosition(undefined); 2203 }) 2204 }); 2205 2206 }); 2207 2208 } 2209 2210 return true; 2211} 2212 2213/** 2214 * Met à jour l'image de la webcam 2215 * @param feature 2216 * @param eventType 2217 * @returns 2218 */ 2219function DDERefreshWebcamFeature(feature, eventType) { 2220 // Retourne si aucun élément 2221 if (!feature) { 2222 return false; 2223 } 2224 2225 // Récupère les propriétés 2226 var properties = feature.getProperties(); 2227 var url = properties.url_script || ''; 2228 var webcamType = properties.config || ''; 2229 var directoryPath = properties.path_dossier || ''; 2230 var directoryUrl = properties.url_dossier || ''; 2231 var idWebcam = properties.id_webcam || '0'; 2232 var webcamMediaType = properties.type_media || ''; 2233 2234 var idDivWebcam = 'webcam_image_' + eventType; 2235 idElementWebcam = $('#' + idDivWebcam).data('id'); 2236 // Vérifie que tout est bien renseigné 2237 if (url === '' || webcamType === '' || directoryPath === '' || idWebcam === '0') { 2238 return false; 2239 } 2240 2241 // pas de rafraichissement pour les vidéo stream 2242 if (properties.config == 'stream' || properties.config == 'animation') { 2243 return false; 2244 } 2245 2246 // Récupère le délai 2247 var delay = properties.delai_rafraichissement || '1000';
2248 delay = parseFloat(delay); 2249 2250 // Vérifie la date de dernière récupération 2251 var currentTimeStamp = Date.now(); 2252 if (properties.lastCallTimeStamp !== undefined && properties.lastCallTimeStamp + delay > currentTimeStamp) { 2253 // Met à jour l'image 2254 DDERefreshWebcamFeatureSpan(feature, eventType); 2255 return true; 2256 } 2257 2258 // Garde la date de dernier appel 2259 feature.setProperties({ lastCallTimeStamp: currentTimeStamp }); 2260 2261 // Récupère l'image 2262 var param = { 2263 type: 'POST', 2264 url: url, 2265 async: true, 2266 crossDomain: true, 2267 data: { 2268 type: webcamType, 2269 dossier: directoryPath, 2270 id: idWebcam, 2271 type_media: webcamMediaType, 2272 }, 2273 dataType: 'json', 2274 }; 2275 2276 // Met à jour l'image 2277 $.ajax(param).done(function (output) { 2278 if (output.result === 'OK') { 2279 // Garde les infos 2280 feature.setProperties({ 2281 directoryUrl: directoryUrl, 2282 last5images: output.last_files_name, 2283 last5imagesIndex: 0, 2284 lastCallImageDate: output.strDate, 2285 lastCallImageSource: directoryUrl + output.filename, 2286 lastCallId: output.id, 2287 }); 2288 2289 // Met à jour l'image 2290 DDERefreshWebcamFeatureSpan(feature, eventType); 2291 } 2292 }); 2293 2294 return true; 2295} 2296 2297/** 2298 * Met à jour l'image de la webcam dans le popup 2299 * @param feature 2300 * @param eventType 2301 * @returns 2302 */ 2303function DDERefreshWebcamFeatureSpan(feature, eventType) { 2304 // Récupère les identifiant des éléments 2305 var idDivWebcam = 'webcam_image_' + eventType; 2306 var idElementWebcam = $('#' + idDivWebcam).data('id'); 2307 2308 // Récupère les propriétés 2309 var properties = feature.getProperties(); 2310 // Met à jour l'image 2311 if ( 2312 properties.lastCallImageDate !== undefined && 2313 properties.lastCallImageSource !== undefined && 2314 properties.lastCallId !== undefined && 2315 properties.lastCallId == idElementWebcam 2316 ) { 2317 $('div[id=' + idDivWebcam + '] span.webcamDate').html(properties.lastCallImageDate); 2318 2319 var link = $('div[id=' + idDivWebcam + '] a[data-webcam-link]'); 2320 if (link.length > 0) { 2321 link.attr('href', properties.lastCallImageSource); 2322 } 2323 2324 if (properties.type_media == 'DEFILEMENT_IMAGE') { 2325 for (var i = 0; i < 5; i++) { 2326 if (properties.last5images[i] === undefined) { 2327 var val = properties.last5images[0]; 2328 } else { 2329 var val = properties.last5images[i]; 2330 } 2331 2332 $('div[id^="' + idDivWebcam + '"] div[data-id="item-' + i + '"] img').attr( 2333 'src', 2334 properties.directoryUrl + val 2335 ); 2336 } 2337 } else if (properties.type_media == 'IMAGE') { 2338 $('div[id^=' + idDivWebcam + '] img').attr('src', properties.lastCallImageSource + '?' + new Date().getTime()); 2339 } else { 2340 var extension = properties.lastCallImageSource.split('.').pop(); 2341 2342 $('div[id^=' + idDivWebcam + '] img').hide(); 2343 $('div[id^=' + idDivWebcam + '] video').hide(); 2344 if (extension == 'mp4' || extension == 'webm') { 2345 $('div[id^=' + idDivWebcam + '] video').show(); 2346 $('div[id^=' + idDivWebcam + '] video source').attr('src', properties.lastCallImageSource); 2347 $('div[id^=' + idDivWebcam + '] video source').attr('type', 'video/' + extension); 2348 } else { 2349 $('div[id^=' + idDivWebcam + '] img').show(); 2350 $('div[id^=' + idDivWebcam + '] img').attr('src', properties.lastCallImageSource + '?' + new Date().getTime()); 2351 } 2352 } 2353 } 2354} 2355 2356/** 2357 * Retourner le template du poup correspondant au type en paramétre 2358 * 2359 * @param {string} type : nom du type de template 2360 * @param {string} position : emplacement dans le popup (_TITRE/_CORPS) 2361 * 2362 * @retrun {string} 2363 */ 2364function getTemplateOfPopup(type, position) { 2365 var sTemplate = typeof templatePopup[type] !== 'undefined' ? templatePopup[type] : undefined; 2366 2367 if (sTemplate === undefined) { 2368 var sErreur = 'Erreur: le template "{{type}}" est indéfini.'; 2369 sTemplate = sErreur; 2370 if (position === '_TITRE') { 2371 if (typeof templatePopup._TITRE !== 'undefined') { 2372 sTemplate = templatePopup._TITRE; 2373 } 2374 } else if (position === '_CORPS') { 2375 //cas particulier des reperes 2376 if ( 2377 typeof templatePopup._REPERE !== 'undefined' && 2378 (type === '_REPEREHEBDO' || 2379 type === '_REPEREANNUEL' || 2380 type === '_REPEREPERMANENT' || 2381 type === '_REPERETIPI') 2382 ) { 2383 sTemplate = templatePopup._REPERE; 2384 } 2385 2386 // Custom 2387 if (typeof templatePopup._CUSTOM_PICTO !== 'undefined' && type === 'CUSTOM_PICTO') { 2388 sTemplate = templatePopup._CUSTOM_PICTO; 2389 } else if (typeof templatePopup._CUSTOM_BARREAU !== 'undefined' && type === 'CUSTOM_BARREAU') { 2390 sTemplate = templatePopup._CUSTOM_BARREAU; 2391 } else if (typeof templatePopup._CUSTOM_ZONE !== 'undefined' && type === 'CUSTOM_ZONE') { 2392 sTemplate = templatePopup._CUSTOM_ZONE; 2393 } else if ( 2394 typeof templatePopup.CUSTOM !== 'undefined' && 2395 (type === 'CUSTOM_PICTO' || type === 'CUSTOM_BARREAU' || type === 'CUSTOM_ZONE') 2396 ) { 2397 sTemplate = templatePopup.CUSTOM; 2398 } else if ( 2399 typeof templatePopup._CUSTOM !== 'undefined' && 2400 (type === 'CUSTOM_PICTO' || type === 'CUSTOM_BARREAU' || type === 'CUSTOM_ZONE') 2401 ) { 2402 sTemplate = templatePopup._CUSTOM; 2403 } 2404 2405 if (sTemplate === sErreur && typeof templatePopup._DEFAUT !== 'undefined') { 2406 sTemplate = templatePopup._DEFAUT; 2407 } 2408 } else { 2409 sTemplate = 'Erreur: la position "' + position + '" est indéfini.'; 2410 } 2411 } 2412 2413 return sTemplate; 2414} 2415 2416/** 2417 * Filtre les calques a associer a un popup ou pas 2418 * @param {object} layer : ol.layer objet calque a tester 2419 * @retun {boolean} 2420 */ 2421function DDELayerFilter(layer) { 2422 var sName = layer.get('name'); 2423 if (sName !== undefined) { 2424 var oConfig = {}; 2425 for (var i in layerConfig) { 2426 oConfig = layerConfig[i]; 2427 if (oConfig.name == sName && oConfig.showpopup) return true; 2428 //cas des sous calques de reperes ou barreaux 2429 if ( 2430 (oConfig.name == 'layer-barreau' || oConfig.name == 'layer-repere') && 2431 oConfig.sublayer !== undefined && 2432 oConfig.sublayer.length > 0 2433 ) { 2434 var oConfigSubLayer = {}; 2435 for (var j in oConfig.sublayer) { 2436 oConfigSubLayer = oConfig.sublayer[j]; 2437 if (oConfigSubLayer.name == sName && oConfigSubLayer.showpopup) return true; 2438 } 2439 } 2440 } 2441 } 2442 return false; 2443} 2444 2445/** 2446 * Filtre les objets d'un calque a associer a un popup ou pas 2447 * 2448 * @param {object} feature : ol.feature objet contenu dans un calque 2449 * @param {object} layer : ol.layer objet calque a tester 2450 * 2451 * @retun ol.feature|false 2452 */ 2453function DDEFeatureFilter(feature, layer) { 2454 if (feature.get('nopopup')) { 2455 return false; 2456 } 2457 2458 var tFeature = feature.get('features'); 2459 if (tFeature === undefined) { 2460 return feature; 2461 } else { 2462 if (tFeature.length === 1) { 2463 //cas des cluster a un evt 2464 return tFeature[0]; 2465 } 2466 } 2467 2468 return false; 2469} 2470 2471/** 2472 * Changer la forme du curseur au survol d'une feature 2473 * 2474 * @param evt 2475 * 2476 * @return void 2477 */ 2478function DDEDetectMouseOver(evt) { 2479 var mapId = document.getElementById('map'), 2480 pixel = oMap.getEventPixel(evt.originalEvent);
2481 var hit = oMap.forEachFeatureAtPixel( 2482 pixel, 2483 function (feature, layer) { 2484 return true; 2485 }, 2486 null, 2487 function (layer) { 2488 return DDELayerFilter(layer); 2489 } 2490 ); 2491 if (hit) { 2492 mapId.style.cursor = 'pointer'; 2493 } else { 2494 mapId.style.cursor = ''; 2495 } 2496} 2497 2498/** 2499 * Retourner la configuration d'un calque 2500 * 2501 * @param {string} config : nom de la configuration 2502 * 2503 * @return object|null 2504 */ 2505function getLayerConfiguration(config) { 2506 if (sUrlAjax !== 'undefined' && sUrlAjax !== '') { 2507 var option = {}; 2508 2509 option.request = typeof config.request !== 'undefined' ? config.request : null; 2510 option.dataContainerId = typeof config.dataContainerId !== 'undefined' ? config.dataContainerId : ''; 2511 option.name = typeof config.name !== 'undefined' ? config.name : 'layer-' + i; 2512 option.label = typeof config.label !== 'undefined' ? config.label : 'Layer ' + i; 2513 option.url = typeof config.url !== 'undefined' && config.url !== 'default' ? config.url : sUrlAjax; 2514 option.action = typeof config.action !== 'undefined' ? config.action : null; 2515 option.style = typeof config.style !== 'undefined' ? config.style : undefined; 2516 option.visibility = typeof config.visibility !== 'undefined' ? config.visibility : false; 2517 option.protection = typeof config.protection !== 'undefined' ? config.protection : false; 2518 option.protectionContainerId = 2519 typeof config.protectionContainerId !== 'undefined' ? config.protectionContainerId : ''; 2520 option.showpopup = typeof config.showpopup !== 'undefined' ? config.showpopup : false; 2521 option.opacity = typeof config.opacity !== 'undefined' ? config.opacity : 1; 2522 option.minResolution = typeof config.minResolution !== 'undefined' ? config.minResolution : undefined; 2523 option.maxResolution = typeof config.maxResolution !== 'undefined' ? config.maxResolution : undefined; 2524 option.order = typeof config.order !== 'undefined' ? config.order : -1; 2525 option.autoUpdate = typeof config.autoUpdate !== 'undefined' ? config.autoUpdate : false; 2526 option.autoUpdateInterval = typeof config.autoUpdateInterval !== 'undefined' ? config.autoUpdateInterval : 0; 2527 option.featureDisplayContainerId = 2528 typeof config.featureDisplayContainerId !== 'undefined' ? config.featureDisplayContainerId : ''; 2529 option.sublayer = typeof config.sublayer !== 'undefined' ? config.sublayer : []; 2530 option.enableClustering = typeof config.enableClustering !== 'undefined' ? config.enableClustering : false; 2531 option.cluster = typeof config.cluster !== 'undefined' ? config.cluster : {}; 2532 2533 return option; 2534 } 2535 2536 return null; 2537} 2538 2539/** 2540 * Ajoute tous les calques à la carte 2541 * 2542 * @param {object} config : configuration des calques 2543 * 2544 * @return void 2545 */ 2546function DDEAddAllLayer(config) { 2547 var option = null; 2548 for (var i in config) { 2549 option = getLayerConfiguration(config[i]); 2550 if (option === null) continue; 2551 2552 if (option.sublayer.length > 0) { 2553 DDEAddSpecialLayer(option); 2554 var sLoggedExtranet = 2555 document.getElementById('loggued-extranet') !== null 2556 ? document.getElementById('loggued-extranet').textContent 2557 : '0'; 2558 var bEnableAutomaticUpdate = false; 2559 if (typeof ENABLE_AUTOMATIC_UPDATE !== 'undefined') bEnableAutomaticUpdate = ENABLE_AUTOMATIC_UPDATE; 2560 if ( 2561 bEnableAutomaticUpdate === true && 2562 option.autoUpdate === true && 2563 (sLoggedExtranet === '1' || option.name === 'layer-trafic') 2564 ) { 2565 //mise a jour automatique des calques 2566 autoUpdateSpecialLayer(i, option.url, option.autoUpdateInterval); 2567 } 2568 } else { 2569 switch (option.request) { 2570 case '_LOCAL': 2571 if (option.dataContainerId !== '') { 2572 var oElement = document.getElementById(option.dataContainerId); 2573 if (oElement !== null) { 2574 var data = null; 2575 try { 2576 data = JSON.parse(oElement.textContent); 2577 DDEAddLayerFromGeoJsonText(data, option); 2578 } catch (e) {} 2579 } 2580 } 2581 break; 2582 case '_KML': 2583 DDEAddLayerFromKml(option); 2584 break; 2585 default: 2586 DDEAddLayerFromGeoJson(option); 2587 var sLoggedExtranet = 2588 document.getElementById('loggued-extranet') !== null 2589 ? document.getElementById('loggued-extranet').textContent 2590 : '0'; 2591 var bEnableAutomaticUpdate = false; 2592 if (typeof ENABLE_AUTOMATIC_UPDATE !== 'undefined') 2593 bEnableAutomaticUpdate = ENABLE_AUTOMATIC_UPDATE; 2594 if ( 2595 bEnableAutomaticUpdate === true && 2596 option.autoUpdate === true && 2597 (sLoggedExtranet === '1' || option.name === 'layer-trafic') 2598 ) { 2599 //mise a jour automatique des calques 2600 autoUpdateLayerFromGeoJson(option.name, option.autoUpdateInterval); 2601 } 2602 } 2603 } 2604 } 2605} 2606 2607/** 2608 * Ajouter un calque à la carte à un index (ordre) donné 2609 * 2610 * @param {ol.layer} layer : calque 2611 * @param {integer} index : numéro d'ordre 2612 * 2613 * @return void 2614 */ 2615function addLayerToMap(layer, index) { 2616 // Définie la profondeur du calque 2617 layer.setZIndex(index); 2618 2619 // Ajoute le calque 2620 oMap.addLayer(layer); 2621} 2622 2623/** 2624 * Recupérer un calque 2625 * 2626 * @param layerName {string} nom du calque 2627 * @returns {ol.layer.Layer} 2628 */ 2629function getLayerByName(layerName) { 2630 var layer = null;
2631 oMap.getLayers().forEach(function (lyr) { 2632 if (typeof lyr === 'object' && lyr.get('name') == layerName) { 2633 layer = lyr; 2634 } 2635 }); 2636 2637 return layer; 2638} 2639 2640/** 2641 * Recupérer un groupe de calques 2642 * 2643 * @param groupName {string} : nom du groupe de calques 2644 * @returns {ol.layer.Group} 2645 */ 2646function getLayerGroupByName(groupName) { 2647 var group = null; 2648 var elementName = ''; 2649 oMap.getLayers().forEach(function (elem) { 2650 if (typeof elem === 'object') { 2651 elementName = elem.get('name'); 2652 if (elementName == groupName) { 2653 group = elem; 2654 } 2655 } 2656 }); 2657 2658 return group; 2659} 2660 2661/** 2662 * Modifie la visibilité d'un calque 2663 * 2664 * @param layerName {string} : nom du calque 2665 * @param visible {boolean} : calque visible ou non 2666 * @returns {Boolean} 2667 */ 2668function setLayerVisibilityByName(layerName, visible) { 2669 var layer; 2670 layer = getLayerByName(layerName); 2671 if (layer !== null) { 2672 layer.setVisible(visible); 2673 return true; 2674 } 2675 2676 return false; 2677} 2678 2679/** 2680 * Bascule la visibilité d'un calque de tuile (carte) 2681 * 2682 * @param layerName {string} : nom du calque 2683 * @returns {Boolean} 2684 */ 2685function toggleTileVisibilityByName(layerName) { 2686 var layer = null; 2687 var visible = false; 2688 var result = false; 2689 var elementName = ''; 2690 var groupName = tileConfig.groupName; 2691 var defaultLayer = tileConfig.defaultLayerName; 2692 2693 layer = getLayerGroupByName(groupName); 2694 2695 if (layer !== null) { 2696 layer.getLayers().forEach(function (elem) { 2697 elementName = elem.get('name'); 2698 if (elementName === layerName && elementName !== defaultLayer) { 2699 visible = elem.getVisible(); 2700 elem.setVisible(!visible); 2701 result = true; 2702 } else if (elementName !== defaultLayer) { 2703 elem.setVisible(false); 2704 } 2705 }); 2706 } 2707 2708 return result; 2709} 2710 2711/** 2712 * Bascule la visibilité d'un calque 2713 * 2714 * exemple (repere cligneton) : setInterval(function(){toggleLayerVisibilityByName('layer-repere')},1000) 2715 * 2716 * @param layerName {string} : nom du calque 2717 * @returns {Boolean} 2718 */ 2719function toggleLayerVisibilityByName(layerName) { 2720 if (layerName === 'layer-trafic' || (typeof visibleLayers !== 'undefined' && visibleLayers.length > 0)) { 2721 toggleDisplayThisLayer('layer-trafic'); 2722 return false; 2723 } 2724 2725 var layer = getLayerByName(layerName); 2726 if (layer !== null) { 2727 var visible = layer.getVisible(); 2728 layer.setVisible(!visible); 2729 setLayerConfigPropertie(layerName, 'visibility', !visible); 2730 return true; 2731 } 2732 2733 return false; 2734} 2735 2736/** 2737 * Zommer vers une region de la carte 2738 * 2739 * @param zoom {integer} : valeur du zoom 2740 * @param longitude {float} : longitude du centre de la vue 2741 * @param latitude {float} : latitude du centre de la vue 2742 * @param projection {string} : projection de la longitude et latitude (par défaut 'EPSG:3857', si 'EPSG:4326' reprojection) 2743 * 2744 * @return void 2745 */ 2746function setViewZoomAndCenter(zoom, longitude, latitude, projection) { 2747 var sProj = projection || 'EPSG:3857'; 2748 var centre = [longitude, latitude]; 2749 if (sProj === 'EPSG:4326') centre = ol.proj.transform([longitude, latitude], 'EPSG:4326', 'EPSG:3857');
2750 setViewCenterWithAnimation(centre); 2751 setViewZoomWithAnimation(zoom); 2752} 2753 2754/** 2755 * Associer une fonction callback à un changement de propreites de la vue 2756 * 2757 * @param propertie string[] : tableau des properietes ('resoltion', 'center', ...) 2758 * @param callback function : fonction de calback a éxecuter 2759 * 2760 * @return boolean 2761 */ 2762function onViewPropertyChange(propertie, callback) { 2763 if (typeof callback == 'function' && Array.isArray(propertie)) { 2764 var oView = oMap.getView(); 2765 oView.on('propertychange', function (e) { 2766 for (var i in propertie) { 2767 if (propertie[i] === e.key) { 2768 callback(); 2769 } 2770 } 2771 }); 2772 2773 return true; 2774 } 2775 2776 return false; 2777} 2778 2779/** 2780 * Retourner la configuration d'un calque (variable layerConfig du fichier script-config.js) 2781 * 2782 * @param string layerName : nom de la configuration du calque 2783 * 2784 * @returns object : configuration du calque ou undefined 2785 */ 2786function getLayerConfig(layerNameConfig) { 2787 return layerConfig[layerNameConfig]; 2788} 2789 2790/** 2791 * Affecter une valeur à une propriete de la configuration d'un calque 2792 * 2793 * @param string layerName : nom du calque 2794 * @param string propertie : nom de la propriete a modifier 2795 * @param string value : valeur a affecter a la propriete 2796 * 2797 * @returns {Boolean} opération réussis ou non 2798 */ 2799function setLayerConfigPropertie(layerName, propertie, value) { 2800 var bResult = false; 2801 //trouver la configuration du calque 2802 for (var j in layerConfig) { 2803 if (layerConfig[j].name === layerName) { 2804 layerConfig[j][propertie] = value; 2805 bResult = true; 2806 break; 2807 } 2808 } 2809 return bResult; 2810} 2811 2812/** 2813 * Mise a jour automatique d'un calque GeoJson 2814 * @param string layerName : nom du calque à mette à jour 2815 * @param integer autoUpdateInterval : délais de mise à jour automatique 2816 * @returns void 2817 */ 2818function autoUpdateLayerFromGeoJson(layerName, autoUpdateInterval) { 2819 setInterval(function () { 2820 DDEUpdateLayerFromGeoJson(layerName); 2821 }, autoUpdateInterval); 2822} 2823 2824/** 2825 * Mise a jour automatique d'un calque speciale (repere) 2826 * 2827 * @param string layerNameConfig : nom de la configuration du calque 2828 * @param string url : url de la requete AJAX 2829 * @param integer autoUpdateInterval : délais de mise à jour automatique 2830 * 2831 * @returns void 2832 */ 2833function autoUpdateSpecialLayer(layerNameConfig, url, autoUpdateInterval) { 2834 setInterval(function () { 2835 var localLayerConfig = getLayerConfig(layerNameConfig); 2836 localLayerConfig.url = localLayerConfig.url !== 'default' ? localLayerConfig.url : url; 2837 DDEAddSpecialLayer(localLayerConfig); 2838 }, autoUpdateInterval); 2839} 2840 2841/** 2842 * Mise à clignoter d'un objet 2843 * 2844 * @param ol.feature feature: objet (evenement) d'un calque 2845 * 2846 * @return void 2847 */ 2848function setBlinking(feature) { 2849 var style = feature.getStyle(); 2850 if (style === null) { 2851 //pas de style <=> icone est visible 2852 var hideIcone = new ol.style.Style({ 2853 image: undefined, 2854 }); 2855 feature.setStyle(hideIcone); 2856 } else { 2857 //style <=> icone invisible 2858 feature.setStyle(null); 2859 } 2860 //refrech 2861 feature.changed(); 2862} 2863 2864/** 2865 * Centrer la carte sur un repère identifié par son ID 2866 * 2867 * @param integer/string id : identifiant du repére 2868 * @param zoom : valeur du zoom 2869 * 2870 * @return boolean centrage réussis ou pas 2871 */ 2872function centerMapOnFeatureId(id, zoom) { 2873 if (typeof zoom === 'undefined') { 2874 zoom = oMap.getView().getZoom(); 2875 } 2876 2877 var oFeature = getRepereById(id); 2878 if (oFeature) { 2879 var tCoord = oFeature.getGeometry().getCoordinates(); 2880 if (typeof tCoord === 'object') { 2881 var oView = oMap.getView(); 2882 oView.setCenter(tCoord); 2883 oView.setZoom(zoom); 2884 return true; 2885 } 2886 } 2887 2888 return false; 2889} 2890 2891/** 2892 * Retourner la liste des noms des calques de repère 2893 * @return {Array} 2894 */ 2895function getAllRepereLayer() { 2896 var tResult = []; 2897 var tRepereSubLayer = layerConfig.repere.sublayer; 2898 if (tRepereSubLayer.length > 0) { 2899 for (var i = 0; i < tRepereSubLayer.length; i++) { 2900 tResult.push(tRepereSubLayer[i].name); 2901 } 2902 } else { 2903 tResult.push(layerConfig.repere.name); 2904 }
2905 return tResult; 2906} 2907 2908/** 2909 * Retourner un repere d'apres son ID 2910 * @param {number|string} id: identifiant du repere 2911 * @return ol.Feature|false 2912 */ 2913function getRepereById(id) { 2914 if (id !== undefined && id !== null) { 2915 var tRepereLayer = getAllRepereLayer(), 2916 i = 0, 2917 oLayer, 2918 oSource, 2919 oFeature; 2920 while (i < tRepereLayer.length) { 2921 oLayer = getLayerByName(tRepereLayer[i]); 2922 if (oLayer) { 2923 oSource = oLayer.getSource(); 2924 if (oSource instanceof ol.source.Cluster) oSource = oSource.getSource(); 2925 oFeature = oSource.getFeatureById(id); 2926 if (oFeature !== null) { 2927 return oFeature; 2928 } 2929 } 2930 i++; 2931 } 2932 } 2933 return false; 2934} 2935 2936function showDialogBox(title, height, width, contentId, modal, timeOut) { 2937 // Retourne si la hauteur, la largeur ou l'élément avec le contenu ne sont 2938 // pas définies 2939 if (height === '' || width === '' || contentId === '' || $('#' + contentId).length <= 0) { 2940 return false; 2941 } 2942 if (typeof tb_show === 'function') { 2943 showDialogBoxTbShow(title, height, width, contentId, modal, timeOut); 2944 } else if (typeof $().dialog === 'function') { 2945 showDialogBoxJQuery(title, height, width, contentId, modal, timeOut); 2946 } else { 2947 return false; 2948 } 2949} 2950 2951function showDialogBoxJQuery(title, height, width, contentId, modal, timeOut) { 2952 $('#' + contentId).dialog({ 2953 title: title, 2954 modal: modal, 2955 width: width, 2956 height: height, 2957 dialogClass: 'custom-dialog', 2958 }); 2959 if (!isNaN(timeOut) && timeOut !== 0) { 2960 setTimeout(function () { 2961 $('#' + contentId).dialog('close'); 2962 }, timeOut); 2963 } 2964 return true; 2965} 2966 2967/** 2968 * Afficher une fenetre de dialogue à fermeture automatique 2969 * utilise ThickBox UI dialog : http://codylindley.com/thickbox/ 2970 * 2971 * @param {string} title : titre de la boite de dialogue 2972 * @param {integer} height : hauteur de la boite de dialogue 2973 * @param {integer} width : largeur de la boite de dialogue 2974 * @param {string} contentId : identifiant de l'element contenant le message à afficher dans la boite de dialogue 2975 * @param {string} modal : affichage modale ou pas ('true'/'false') 2976 * @param {integer} timeOut : delais en milisecondes avant la fermeture de la boite de dialogue (0 desactive la fermeture automatique) 2977 * 2978 * @return {boolean} affichage réussis ou pas de le fenetre de dialogue 2979 * 2980 * @FIXME Essayer de trouver et remplacer par un truc équivalent à ThickBox qui 2981 * soit un peu plus responsive ? 2982 */ 2983function showDialogBoxTbShow(title, height, width, contentId, modal, timeOut) { 2984 // Définie l'url de paramétrage pour thickbox 2985 var sUrl = '#TB_inline?' + 'height=' + height + '&width=' + width + '&inlineId=' + contentId; 2986 2987 if (modal !== '') { 2988 sUrl += '&modal=' + modal; 2989 } 2990 2991 // Affiche la fenêtre 2992 tb_show(title, sUrl, 'false'); 2993 2994 if (!isNaN(timeOut) && timeOut !== 0) { 2995 setTimeout(function () { 2996 tb_remove(); 2997 }, timeOut); 2998 } 2999 return true; 3000} 3001 3002/** 3003 * Ajouter un paragraphe dans une DIV caché ou modifie son contenu s'il existe déja 3004 * @param {string} divId : identifiant de la DIV 3005 * @param {string} divClass : class de la DIV 3006 * @param {string} content : contenu du paragraph 3007 * @returns {Boolean} ajout réussis ou pas du paragraphe 3008 */ 3009function addParagraphInHiddenDiv(divId, divClass, content) { 3010 var bResult = false; 3011 var parentDiv = document.getElementsByClassName('hiddenData')[0]; 3012 if (parentDiv !== undefined) { 3013 if ($('#' + divId).length === 0) { 3014 var newDiv = document.createElement('div'); 3015 newDiv.setAttribute('id', divId); 3016 newDiv.setAttribute('class', divClass); 3017 var newP = document.createElement('p'); 3018 var newText = document.createTextNode(content); 3019 newP.appendChild(newText); 3020 newDiv.appendChild(newP); 3021 parentDiv.appendChild(newDiv); 3022 } else { 3023 var div = document.getElementById(divId); 3024 div.children[0].innerHTML = content; 3025 } 3026 bResult = true; 3027 } 3028 return bResult; 3029} 3030 3031/** 3032 * Gérer la sélection des déviations par la souris 3033 * - Afficher/cacher les déviations 3034 * @param {ol.feature} feature : élément d'une déviation (objet) 3035 * @parm {boolean} selected : objet selectionné ou pas 3036 * @return void 3037 */ 3038function manageDeviationSelection(feature, selected) { 3039 if ( 3040 feature instanceof ol.Feature && 3041 feature.get('type') === '_DEVIATION' && 3042 feature.get('type_deviation') === 'ROUTE_COUPEE' && 3043 feature.get('ids_deviation').length >= 1 3044 ) { 3045 var tDeviation = feature.get('ids_deviation'), 3046 oFeature = null, 3047 tStyle, 3048 i; 3049 for (i = 0; i < tDeviation.length; i++) { 3050 oFeature = getLayerFeatureById('layer-deviation', tDeviation[i]); 3051 if (oFeature !== null) { 3052 if (selected) { 3053 tStyle = getComplexeEventStyle(oFeature); 3054 oFeature.setStyle(tStyle); 3055 } else oFeature.setStyle(null); 3056 } 3057 } 3058 } 3059} 3060 3061/** 3062 * Gérer l'affichage des déviations 3063 * - Afficher/cacher les déviations 3064 * @param {array} tDeviation : tableau des élément composant la déviation 3065 * @parm {boolean} selected : objet selectionné ou pas 3066 * @return void 3067 */ 3068function manageDeviationsDisplay(tDeviation, selected) { 3069 for (i = 0; i < tDeviation.length; i++) { 3070 var oFeature = getLayerFeatureById('layer-deviation', tDeviation[i]); 3071 if (oFeature !== null) { 3072 if (selected) { 3073 var tStyle = getComplexeEventStyle(oFeature); 3074 oFeature.setStyle(tStyle); 3075 } else oFeature.setStyle(null); 3076 } 3077 } 3078} 3079/** 3080 * Gérer l'affichage des déviations par onglet 3081 * - Afficher/cacher les déviations par onglet 3082 * @param {array} tDeviation : tableau des élément composant la déviation 3083 * @parm {boolean} selected : objet selectionné ou pas 3084 * @return void 3085 */ 3086function manageDeviationsDisplayByOnglet(tDeviation, selected){
3087 let currentonglet; 3088 $('.NavigationTab li a').each(function() { 3089 if ($(this).attr('aria-selected') === 'true') { 3090 currentonglet = $(this).attr('aria-controls'); 3091 } 3092 }); 3093 let typesDeviationTodisplay = getTypesDeviationToDisplay(currentonglet); 3094 for (i = 0; i < tDeviation.length; i++) { 3095 let oFeature = getLayerFeatureById('layer-deviation', tDeviation[i]); 3096 let typeDeviation = oFeature.get('type_deviation'); 3097 if (oFeature !== null) { 3098 if (selected && typesDeviationTodisplay.includes(typeDeviation)) { 3099 let tStyle = getComplexeEventStyle(oFeature); 3100 oFeature.setStyle(tStyle); 3101 } else { 3102 oFeature.setStyle(null); 3103 }; 3104 } 3105 } 3106} 3107/** 3108 * 3109 * @param {*} onglet 3110 * @returns array types 3111 */ 3112function getTypesDeviationToDisplay(onglet){ 3113 let types=[]; 3114 const deviations = [ 3115 { selector: '#divDeviationPL', type: 'DEVIATION_PL' }, 3116 { selector: '#divDeviationVL', type: 'DEVIATION_VL' } 3117 ]; 3118 3119 for (let i = 0; i < deviations.length; i++) { 3120 let onglets = []; 3121 if ($(deviations[i].selector).length > 0) { 3122 onglets = $(deviations[i].selector).attr('data-onglet').split(',') 3123 } 3124 3125 if (onglets.includes(onglet)) { 3126 types.push(deviations[i].type); 3127 } 3128 } 3129 return types; 3130} 3131 3132/** 3133 * Retourner un objet d'un calque sur la base de l'id de l'object et le nom du calque 3134 * @param {string} layerName nom du calque 3135 * @param {string|number} id identifiant de l'objet 3136 * @return {ol.feature|null} 3137 */ 3138function getLayerFeatureById(layerName, id) { 3139 var oLayer = getLayerByName(layerName); 3140 if (oLayer !== null) return oLayer.getSource().getFeatureById(id); 3141 return null; 3142} 3143 3144/** 3145 * Geocoder une adresse avec le service nominatiom (http://wiki.openstreetmap.org/wiki/FR:Nominatim) 3146 * - utilisation 3147 * var nom = new nominatim({limit:2}); 3148 * var res = nom.search('dijon',console.log); 3149 * 3150 * @param {object} opt : option de configuration de l'API nominatim : 3151 * {string} opt.url : valeur par défaut = 'http://nominatim.openstreetmap.org/search/' 3152 * {object} opt.params : parmétres de la requete: 3153 * {string} opt.params.query : adresse a rechercher 3154 * {string html|xml|json|jsonv2} opt.params.format : format de la requete AJAX (valeur par défaut 'json') 3155 * {integer 0|1} opt.params.addressdetails : inclure une décomposition de l'adresse en éléments (valeur par défaut 1) 3156 * {interger} opt.params.limit : limiter le nombre de résultats retournés (valeur par défaut 5) 3157 * {string} opt.params.countrycodes : limite les résultats de recherche à un pays spécifique (ou une liste de pays) (valeur par défaut 'FR') 3158 * {string} opt.params.lang : permet de surcharger le language par défaut du navigateur avec un langage pour les résultats de recherche (valeur par défaut 'fr-FR') 3159 * 3160 * @return void 3161 */ 3162function nominatim(opt) { 3163 var options = opt || {}; 3164 var htmlEscape = function (str) { 3165 return String(str) 3166 .replace(/&/g, '&') 3167 .replace(/</g, '<') 3168 .replace(/>/g, '>') 3169 .replace(/"/g, '"') 3170 .replace(/'/g, '''); 3171 }; 3172 this.settings = { 3173 url: 'https://nominatim.openstreetmap.org/search', 3174 params: { 3175 q: '', 3176 format: options.format || 'json', 3177 addressdetails: options.addressdetails || 1, 3178 limit: options.limit || 5, 3179 countrycodes: options.countrycodes || 'FR', 3180 'accept-language': options.lang || 'fr-FR', 3181 }, 3182 }; 3183 3184 var cleanCacheKey = function (str) { 3185 return str.replace(/\s/g, '').toLowerCase(); 3186 }; 3187 3188 var cache = {}; 3189 3190 var setCache = function (q, results) { 3191 var query = cleanCacheKey(q); 3192 if (cache[query] === undefined) { 3193 cache[query] = JSON.stringify(results); 3194 return true; 3195 } 3196 3197 return false; 3198 }; 3199 3200 var getCache = function (q) { 3201 var query = cleanCacheKey(q); 3202 if (cache[query] !== undefined) return JSON.parse(cache[query]); 3203 return false; 3204 }; 3205 3206 this.search = function (query, callback) { 3207 if (query !== undefined && query !== '') this.settings.params.q = htmlEscape(query); 3208 if (this.settings.params.q !== '' && typeof callback === 'function') { 3209 //test cache 3210 var q = cleanCacheKey(query); 3211 if (cache[q] !== undefined) { 3212 callback(getCache(query)); 3213 } else { 3214 //ajax 3215 $.ajax({
3216 type: 'GET', 3217 url: this.settings.url, 3218 async: true, 3219 data: this.settings.params, 3220 dataType: 'json', 3221 }) 3222 .done(function (data) { 3223 setCache(query, data); 3224 callback(data); 3225 }) 3226 .fail(function (jqXHR, textStatus) { 3227 console.log('erreur Nominatim: ' + textStatus); 3228 }); 3229 } 3230 } 3231 }; 3232} 3233 3234/** 3235 * Creation d'un élement du DOM 3236 * 3237 * @param {string} type : type d'élément à créer (button, input, .... 3238 * @param {string []} : tabelau des propriétées de l'élment a créer :[['prop1','value1'],['prop2','value2'], ...] 3239 * eExemple [['id', 'MapControl-search-result'], ['class', 'MapControl-search-result']] 3240 * 3241 * @return object 3242 */ 3243function domCreateElement(type, attribute) { 3244 var element = document.createElement(type); 3245 if (Array.isArray(attribute)) { 3246 attribute.forEach(function (elem) { 3247 if (elem[0] !== undefined && elem[1] !== undefined) element.setAttribute(elem[0], elem[1]); 3248 }); 3249 } 3250 3251 return element; 3252} 3253 3254/** 3255 * Ajouter le controleur de Recherche d'adresse (geocodage) 3256 * - Transformer une adresse en position géographique (latitude/longitude) 3257 * - afficher un popup à l'adresse choisis 3258 * 3259 * @return void 3260 */ 3261function addSearchControl() { 3262 //défintion d'un espace de nom pour l'application 3263 window.app = window.app || {}; 3264 var app = window.app; 3265 3266 /** 3267 * @constructor 3268 * @extends {ol.control.Control} 3269 * @param {Object=} opt_options Control options. 3270 */ 3271 app.SearchControl = function (opt_options) { 3272 var options = opt_options || {}; 3273 options.provider = new nominatim(options.providerOptions); 3274 3275 var handleAddressClik = function (address) { 3276 var view = oMap.getView(), 3277 projection = view.getProjection(), 3278 coord = ol.proj.transform([parseFloat(address.lon), parseFloat(address.lat)], 'EPSG:4326', projection), 3279 overlay = oMap.getOverlays().item(0), 3280 popUpTitle = document.getElementById('popover-title'), 3281 popUpContent = document.getElementById('popover-content'); 3282 3283 overlay.setPosition(undefined); 3284 popUpTitle.innerHTML = address.address.state || address.address.country || ''; 3285 popUpContent.innerHTML = address.display_name; 3286 overlay.setPosition(coord); 3287 3288 view.setCenter(coord); 3289 }; 3290 3291 var setNoResult = function () { 3292 var ulElement = document.getElementById('MapControl-search-result'), 3293 noResultsLabel = options.noResultsLabel || '0 résultats', 3294 liElement; 3295 ulElement.innerHTML = ''; 3296 liElement = document.createElement('li'); 3297 liElement.innerHTML = noResultsLabel; 3298 ulElement.appendChild(liElement); 3299 }; 3300 3301 var displaySearchResults = function (result) { 3302 if (result.length > 0) { 3303 var ulElement = document.getElementById('MapControl-search-result'), 3304 liElement; 3305 ulElement.innerHTML = ''; 3306 3307 result.forEach(function (address) { 3308 var html = '<a href="#">' + address.display_name + '</a>'; 3309 liElement = document.createElement('li'); 3310 liElement.innerHTML = html; 3311 liElement.addEventListener( 3312 'click', 3313 function (evt) { 3314 handleAddressClik(address); 3315 }, 3316 false 3317 ); 3318 ulElement.appendChild(liElement); 3319 }); 3320 } else setNoResult(); 3321 }; 3322 3323 var handleQuery = function (evt) { 3324 if (evt.keyCode == 13) { 3325 var inputElement = document.getElementById('MapControl-search-input'), 3326 query = inputElement.value; 3327 options.provider.search(query, displaySearchResults); 3328 } 3329 }; 3330 3331 var createSearchView = function () { 3332 //bouton 3333 var title = options.tipLabel || 'Rechercher un lieu', 3334 buttonAttribute = [ 3335 ['title', title], 3336 ['id', 'MapControl-search-button'], 3337 ['class', 'MapControl-search-button'], 3338 ['aria-controls', 'SearchArea'], 3339 ['aria-expanded', 'false'], 3340 ], 3341 button = domCreateElement('button', buttonAttribute); 3342 3343 //div recherche 3344 var divSearchAttribute = [ 3345 ['id', 'SearchArea'], 3346 ['class', 'SearchArea'], 3347 ['aria-hidden', 'true'], 3348 ], 3349 divSearch = domCreateElement('div', divSearchAttribute); 3350 3351 //input du div de recherche 3352 var placeHolder = options.placeHolder || 'Rechercher ...', 3353 divSearchInputAttribute = [ 3354 ['type', 'text'], 3355 ['id', 'MapControl-search-input'], 3356 ['class', 'MapControl-search-input'], 3357 ['placeholder', placeHolder], 3358 ], 3359 divSearchInput = domCreateElement('input', divSearchInputAttribute); 3360 divSearchInput.addEventListener('keydown', handleQuery, false); 3361 divSearch.appendChild(divSearchInput); 3362 3363 //list des resultats 3364 var divSearchUnorderedListAttribute = [ 3365 ['id', 'MapControl-search-result'], 3366 ['class', 'MapControl-search-result'], 3367 ], 3368 divSearchUnorderedList = domCreateElement('ul', divSearchUnorderedListAttribute); 3369 divSearch.appendChild(divSearchUnorderedList); 3370 3371 var element = document.createElement('div'); 3372 element.className = 'ol-search ol-unselectable ol-control'; 3373 element.appendChild(button); 3374 element.appendChild(divSearch); 3375 3376 return element; 3377 }; 3378 3379 ol.control.Control.call(this, { 3380 element: createSearchView(), 3381 target: options.target, 3382 }); 3383 }; 3384 3385 ol.inherits(app.SearchControl, ol.control.Control); 3386} 3387 3388/** 3389 * calcul d'itinéraire avec OSRM (Open Source Routing Machine: The OpenStreetMap Data Routing Engine) 3390 * wiki: https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#general-
3390options 3391 * Exemple : 3392 * var osrm = new OSRM(); 3393 * osrm.route({ 3394 * coordinates: [[13.438640,52.519930], [13.415852,52.513191]], 3395 * steps: true, 3396 * alternatives: false, 3397 * overview: 'simplified', 3398 * geometries: 'polyline' 3399 * },console.log); 3400 * 3401 * @param {object} opt : option de configuration de l'API OSRM : 3402 * {string} opt.server : url du serveur (valeur par défaut = 'https://router.project-osrm.org') 3403 * {string} opt.version : version du service (valeur par défaut = 'v1') 3404 * {string} opt.profile : mode de transport (valeur par défaut = 'driving') * 3405 * 3406 * @return void 3407 * 3408 */ 3409function OSRM(opt) { 3410 var options = opt || {}; 3411 3412 this.server = options.server || 'https://router.project-osrm.org'; 3413 this.version = options.version || 'v1'; 3414 this.profile = options.profile || 'driving'; 3415 3416 //filter une option des autres 3417 this.filterOptions = function (options, keys) { 3418 var filtered = {}; 3419 for (var k in options) { 3420 if (keys.indexOf(k) >= 0) { 3421 continue; 3422 } 3423 filtered[k] = options[k]; 3424 } 3425 return filtered; 3426 }; 3427 3428 //transformer un tableau de coordonnées en texte 3429 this.stringifyCoordinates = function (lonLats) { 3430 return lonLats 3431 .map(function (c) { 3432 return c[0] + ',' + c[1]; 3433 }) 3434 .join(';'); 3435 }; 3436 3437 //former l'url de la requete 3438 this.encodeURL = function (service, query) { 3439 var url = this.server + '/' + service + '/' + this.version + '/' + this.profile + '/' + query + '.json'; 3440 return url; 3441 }; 3442 3443 //service route 3444 this.route = function (options, callback) { 3445 var query = this.stringifyCoordinates(options.coordinates), 3446 url = this.encodeURL('route', query), 3447 params = this.filterOptions(options, ['coordinates']); 3448 3449 var divItineraire = $('#ItineraryArea'); 3450 3451 //ajax 3452 $.ajax({
3453 type: 'GET', 3454 url: url, 3455 async: true, 3456 data: params, 3457 dataType: 'json', 3458 statusCode: { 3459 429: function () { 3460 // Cas où on a l'erreur too many request, on y peut rien don on affiche un message plus rassurant que rien du tout 3461 if (divItineraire) { 3462 var string = 3463 '<p style="color:orange; font-weight: bold;"> Service temporairement indisponible. Nous nous excusons pour la gêne occasionnée, veuillez réessayer plus tard. Rétablissement imminent</p>'; 3464 $('#MapControl-itinerary-summary').html(string); 3465 } 3466 }, 3467 }, 3468 }) 3469 .done(function (data) { 3470 callback(data); 3471 }) 3472 .fail(function (jqXHR, textStatus) { 3473 console.log('erreur OSRM: ' + textStatus); 3474 }); 3475 }; 3476} 3477 3478/** 3479 * Ajouter le controleur de calcul d'itinéraire 3480 * 3481 * @return void 3482 */ 3483function addItineraryControl() { 3484 //défintion d'un espace de nom pour l'application 3485 window.app = window.app || {}; 3486 var app = window.app; 3487 3488 /** 3489 * @constructor 3490 * @extends {ol.control.Control} 3491 * @param {Object=} opt_options Control options. 3492 */ 3493 app.ItineraryControl = function (opt_options) { 3494 var options = opt_options || {}; 3495 3496 //osrm 3497 options.provider = new OSRM(); 3498 options.finder = new nominatim(options.searchOptions); 3499 3500 //layer 3501 options.layer = {}; 3502 options.layer.styleFunction = function (feature, resolution) { 3503 var image = new ol.style.Icon({ 3504 anchor: [0.5, 1], 3505 opacity: 1, 3506 src: feature.get('src') || 'images/image.png', 3507 scale: feature.get('scale') || 0.7, 3508 }); 3509 3510 var styles = { 3511 Point: [ 3512 new ol.style.Style({ 3513 image: image, 3514 }), 3515 ], 3516 LineString: [ 3517 new ol.style.Style({ 3518 stroke: new ol.style.Stroke({ 3519 color: [0, 51, 255, 0.3], 3520 linecap: 'round', 3521 linejoin: 'round', 3522 width: 10, 3523 }), 3524 }), 3525 ], 3526 }; 3527 3528 return styles[feature.getGeometry().getType()]; 3529 }; 3530 options.layer.vectorSource = new ol.source.Vector({}); 3531 options.layer.vectorLayer = new ol.layer.Vector({ 3532 name: 'layer-itinerary', 3533 label: 'Calque des itinéraires', 3534 source: options.layer.vectorSource, 3535 style: options.layer.styleFunction, 3536 }); 3537 addLayerToMap(options.layer.vectorLayer, 99); 3538 3539 var getItineraryStepsHTML = function (steps) { 3540 var stepsHTML = 3541 '<table class="MapControl-itinerary-steps-table"><colgroup class="MapControl-itinerary-steps-colgroup"><col class="MapControl-itinerary-steps-col-icon"><col class="MapControl-itinerary-steps-col-text"><col class="MapControl-itinerary-steps-col-duration"><col class="MapControl-itinerary-steps-col-distance"></colgroup><tbody class="MapControl-itinerary-steps-table-tbody">', 3542 modifier, 3543 type, 3544 duration, 3545 distance; 3546 3547 for (var i = 0; i < steps.length; i++) { 3548 stepsHTML += '<tr>'; 3549 3550 //icon 3551 type = 3552 typeof steps[i].maneuver.type !== 'undefined' 3553 ? '-' + steps[i].maneuver.type.replace(/\s/g, '-') 3554 : ''; 3555 modifier = 3556 typeof steps[i].maneuver.modifier !== 'undefined' && type !== '-depart' && type !== '-arrive' 3557 ? '-' + steps[i].maneuver.modifier.replace(/\s/g, '-') 3558 : ''; 3559 stepsHTML += 3560 '<td ><span class="MapControl-itinerary-steps-icon MapControl-itinerary-steps-icon' + 3561 type + 3562 modifier + 3563 '"></span></td>'; 3564 3565 //text 3566 stepsHTML += '<td>' + steps[i].name + '</td>'; 3567 3568 //duration 3569 duration = steps[i].duration / 60; 3570 stepsHTML += '<td>' + Math.round(duration) + ' min</td>'; 3571 3572 //distance 3573 distance = steps[i].distance / 1000; 3574 stepsHTML += '<td>' + Math.round(distance * 100) / 100 + ' Km</td></tr>'; 3575 } 3576 3577 stepsHTML += '</tbody></table>'; 3578 return stepsHTML; 3579 }; 3580 3581 var deleteFeatureById = function (id, vectorSource) { 3582 var oldFeature = vectorSource.getFeatureById(id);
3583 if (oldFeature !== null) vectorSource.removeFeature(oldFeature); 3584 }; 3585 3586 var drawMarkerOnMap = function (coordinates, id, src, scale, vectorSource) { 3587 //delete old feature 3588 deleteFeatureById(id, vectorSource); 3589 3590 //new feature 3591 var markerGeom = new ol.geom.Point(coordinates); 3592 3593 var markerFeature = new ol.Feature({ 3594 geometry: markerGeom, 3595 }); 3596 markerFeature.setId(id); 3597 markerFeature.setProperties({ 3598 src: src, 3599 scale: scale, 3600 }); 3601 3602 //add feature 3603 vectorSource.addFeature(markerFeature); 3604 }; 3605 3606 var drawItineraryOnMap = function (routeGeometry, id, vectorSource) { 3607 //delete old feature 3608 deleteFeatureById(id, vectorSource); 3609 3610 //new feature 3611 var routeGeom = new ol.format.Polyline({ 3612 factor: 1e5, 3613 }).readGeometry(routeGeometry, { 3614 dataProjection: 'EPSG:4326', 3615 featureProjection: 'EPSG:3857', 3616 }); 3617 3618 //add feature 3619 var routeFeature = new ol.Feature({ 3620 geometry: routeGeom, 3621 }); 3622 routeFeature.setId(id); 3623 vectorSource.addFeature(routeFeature); 3624 3625 //add start marker 3626 var routeCoords = routeGeom.getCoordinates(); 3627 var routeLength = routeCoords.length; 3628 drawMarkerOnMap(routeCoords[0], 1, 'images/itinerary_marker_green.png', 0.7, vectorSource); 3629 3630 //add end marker 3631 drawMarkerOnMap(routeCoords[routeLength - 1], 3, 'images/itinerary_marker_red.png', 0.7, vectorSource); 3632 3633 //fit view 3634 var view = oMap.getView(); 3635 view.fit(routeGeom, oMap.getSize()); 3636 }; 3637 3638 var displayItineraryResults = function (result) { 3639 var summaryElement = document.getElementById('MapControl-itinerary-summary'), 3640 resultElement = document.getElementById('MapControl-itinerary-steps'); 3641 if (result.code === 'Ok') { 3642 var itinerary = typeof result.routes[0].legs[0] !== 'undefined' ? result.routes[0].legs[0] : undefined; 3643 3644 if (itinerary !== undefined) { 3645 //summary 3646 if (summaryElement !== null) { 3647 var summaryHTML = '', 3648 distance = typeof itinerary.distance !== 'undefined' ? itinerary.distance / 1000 : 0, 3649 duration = typeof itinerary.duration !== 'undefined' ? itinerary.duration / 60 : 0; 3650 summaryHTML += itinerary.summary !== '' ? '<p> Trajet : ' + itinerary.summary + '</p>' : ''; 3651 summaryHTML += '<p> Distance : ' + Math.round(distance * 10) / 10 + ' Km </p>'; 3652 summaryHTML += '<p> Durée : ' + Math.round(duration) + ' minutes </p>'; 3653 summaryElement.innerHTML = summaryHTML; 3654 } 3655 3656 //steps 3657 if ( 3658 typeof itinerary.steps !== 'undefined' && 3659 itinerary.steps.length > 0 && 3660 resultElement !== null 3661 ) { 3662 resultElement.innerHTML = getItineraryStepsHTML(itinerary.steps); 3663 } 3664 3665 //trace 3666 if (typeof result.routes[0].geometry !== 'undefined' && result.routes[0].geometry !== '') 3667 drawItineraryOnMap(result.routes[0].geometry, 2, options.layer.vectorSource); 3668 } 3669 } else if (result.code === 'NoRoute') { 3670 summaryElement.innerHTML = '<p> Pas de route trouvée. </p>'; 3671 resultElement.innerHTML = ''; 3672 } 3673 }; 3674 3675 var checkLonLat = function (str) { 3676 var pattern = /-?[0-9]{1,3}[.][0-9]+/; 3677 if (pattern.test(str)) { 3678 var tCoord = str.split(','); 3679 if (tCoord.length === 2 && pattern.test(tCoord[0]) && pattern.test(tCoord[1])) { 3680 var lon = parseFloat(tCoord[0]), 3681 lat = parseFloat(tCoord[1]); 3682 if (!isNaN(lon) && !isNaN(lat) && lon >= -180 && lon <= 180 && lat >= -90 && lat <= 90) return true; 3683 } 3684 } 3685 return false; 3686 }; 3687 3688 var deletePreviousSibling = function (evt) { 3689 var elementPreviousSibling = document.getElementById(evt.target.id).previousSibling; 3690 elementPreviousSibling.value = ''; 3691 }; 3692 3693 var changeActiveInput = function (evt) { 3694 var divItinerarySearch = document.getElementById('MapControl-itinerary-search'); 3695 if (divItinerarySearch !== null) divItinerarySearch.setAttribute('data-active-input', evt.target.id); 3696 }; 3697 3698 var handleQuery = function (evt) { 3699 var inputElementStart = document.getElementById('MapControl-itinerary-search-start-input'), 3700 inputElementEnd = document.getElementById('MapControl-itinerary-search-en
3700d-input'); 3701 document.getElementById('MapControl-itinerary-search-Suggestions-list').innerHTML = ''; 3702 if (inputElementStart !== null && inputElementEnd !== null) { 3703 var start = inputElementStart.getAttribute('data-position').replace(/\s/g, ''), 3704 end = inputElementEnd.getAttribute('data-position').replace(/\s/g, ''); 3705 if (start !== '' && end !== '' && checkLonLat(start) && checkLonLat(end)) { 3706 var tStart = start.split(','), 3707 tEnd = end.split(','), 3708 tCoord = [tStart, tEnd]; 3709 options.provider.route( 3710 { 3711 coordinates: tCoord, 3712 steps: false, 3713 alternatives: false, 3714 overview: 'simplified', 3715 geometries: 'polyline', 3716 }, 3717 displayItineraryResults 3718 ); 3719 } 3720 } 3721 }; 3722 3723 var handleAddressClik = function (address) { 3724 document.getElementById('MapControl-itinerary-search-Suggestions-list').innerHTML = ''; 3725 var divItinerarySearch = document.getElementById('MapControl-itinerary-search'); 3726 if (divItinerarySearch !== null) { 3727 var IdActiveInput = divItinerarySearch.getAttribute('data-active-input'), 3728 inputElement = document.getElementById(IdActiveInput); 3729 if (inputElement !== null && inputElement.offsetWidth > 0 && inputElement.offsetHeight > 0) { 3730 var coord = address.lon + ', ' + address.lat; 3731 inputElement.value = address.display_name || coord; 3732 inputElement.setAttribute('data-position', coord); 3733 } 3734 } 3735 }; 3736 3737 var displaySearchResults = function (result) { 3738 var ulElement = document.getElementById('MapControl-itinerary-search-Suggestions-list'), 3739 liElement; 3740 ulElement.innerHTML = ''; 3741 3742 if (result.length > 0) { 3743 result.forEach(function (address) { 3744 liElement = document.createElement('li'); 3745 liElement.innerHTML = address.display_name; 3746 liElement.addEventListener( 3747 'click', 3748 function (evt) { 3749 handleAddressClik(address); 3750 }, 3751 false 3752 ); 3753 ulElement.appendChild(liElement); 3754 }); 3755 } 3756 }; 3757 3758 var findAddress = function (evt) { 3759 if (evt.keyCode == 13) { 3760 options.finder.search(this.value, displaySearchResults); 3761 } 3762 }; 3763 3764 var handleLayerVisibility = function () { 3765 options.layer.vectorLayer.setVisible(this.checked); 3766 }; 3767 3768 var createItineraryView = function () { 3769 //bouton du controleur 3770 var title = options.tipLabel || "calcul d'itinéraire", 3771 buttonAttribute = [ 3772 ['title', title], 3773 ['id', 'MapControl-itinerary-button'], 3774 ['class', 'MapControl-itinerary-button'], 3775 ['aria-controls', 'ItineraryArea'], 3776 ['aria-expanded', 'false'], 3777 ], 3778 controlButton = domCreateElement('button', buttonAttribute); 3779 3780 //div itineraire 3781 var divItineraryAttribute = [ 3782 ['id', 'ItineraryArea'], 3783 ['class', 'ItineraryArea'], 3784 ['aria-hidden', 'true'], 3785 ], 3786 divItinerary = domCreateElement('div', divItineraryAttribute); 3787 3788 //div recherche 3789 var divItinerarySearchAttribute = [ 3790 ['id', 'MapControl-itinerary-search'], 3791 ['class', 'MapControl-itinerary-search'], 3792 ['data-active-input', 'MapControl-itinerary-search-start-input'], 3793 ], 3794 divItinerarySearch = domCreateElement('div', divItinerarySearchAttribute); 3795 divItinerary.appendChild(divItinerarySearch); 3796 3797 //div start 3798 var divStartInputAttribute = [ 3799 ['id', 'MapControl-itinerary-search-start'], 3800 ['class', 'MapControl-itinerary-search-location'], 3801 ], 3802 divStartInput = domCreateElement('div', divStartInputAttribute); 3803 divItinerarySearch.appendChild(divStartInput); 3804 3805 //span icone 3806 var spanStartAttribute = [ 3807 ['id', 'MapControl-itinerary-search-icon-depart'], 3808 ['class', 'MapControl-itinerary-search-icon'], 3809 ], 3810 spanStart = domCreateElement('span', spanStartAttribute); 3811 divStartInput.appendChild(spanStart); 3812 3813 //input 3814 var placeHolder = options.placeHolder || 'Entrez une adresse', 3815 inputStartAttribute = [ 3816 ['id', 'MapControl-itinerary-search-start-input'], 3817 ['class', 'MapControl-itinerary-search-input'],
3818 ['data-position', ''], 3819 ['placeholder', placeHolder], 3820 ], 3821 inputStart = domCreateElement('input', inputStartAttribute); 3822 inputStart.addEventListener('click', changeActiveInput, false); 3823 inputStart.addEventListener('keydown', findAddress, false); 3824 divStartInput.appendChild(inputStart); 3825 3826 //button delete 3827 var buttonDelStartAttribute = [ 3828 ['id', 'MapControl-itinerary-search-start-delete'], 3829 ['class', 'MapControl-itinerary-search-delete'], 3830 ], 3831 buttonStart = domCreateElement('button', buttonDelStartAttribute); 3832 buttonStart.addEventListener('click', deletePreviousSibling, false); 3833 divStartInput.appendChild(buttonStart); 3834 3835 //div end 3836 var divEndAttribute = [ 3837 ['id', 'MapControl-itinerary-search-end'], 3838 ['class', 'MapControl-itinerary-search-location'], 3839 ], 3840 divEndInput = domCreateElement('div', divEndAttribute); 3841 divItinerarySearch.appendChild(divEndInput); 3842 3843 //span icone 3844 var spanEndAttribute = [ 3845 ['id', 'MapControl-itinerary-search-icon-end'], 3846 ['class', 'MapControl-itinerary-search-icon'], 3847 ], 3848 spanEnd = domCreateElement('span', spanEndAttribute); 3849 divEndInput.appendChild(spanEnd); 3850 3851 //input 3852 var inputEndAttribute = [ 3853 ['id', 'MapControl-itinerary-search-end-input'], 3854 ['class', 'MapControl-itinerary-search-input'], 3855 ['data-position', ''], 3856 ['placeholder', placeHolder], 3857 ], 3858 inputEnd = domCreateElement('input', inputEndAttribute); 3859 inputEnd.addEventListener('click', changeActiveInput, false); 3860 inputEnd.addEventListener('keydown', findAddress, false); 3861 divEndInput.appendChild(inputEnd); 3862 3863 //button delete 3864 var buttonDelEndAttribute = [ 3865 ['id', 'MapControl-itinerary-search-end-delete'], 3866 ['class', 'MapControl-itinerary-search-delete'], 3867 ], 3868 buttonEnd = domCreateElement('button', buttonDelEndAttribute); 3869 buttonEnd.addEventListener('click', deletePreviousSibling, false); 3870 divEndInput.appendChild(buttonEnd); 3871 3872 //div suggestion 3873 var divSuggestionsAttribute = [ 3874 ['id', 'MapControl-itinerary-search-Suggestions'], 3875 ['class', 'MapControl-itinerary-search-Suggestions'], 3876 ], 3877 divSuggestions = domCreateElement('div', divSuggestionsAttribute); 3878 divItinerarySearch.appendChild(divSuggestions); 3879 3880 //ul suggestion 3881 var ulSuggestionsAttribute = [ 3882 ['id', 'MapControl-itinerary-search-Suggestions-list'], 3883 ['class', 'MapControl-itinerary-search-Suggestions-list'], 3884 ], 3885 ulSuggestionsList = domCreateElement('ul', ulSuggestionsAttribute); 3886 divSuggestions.appendChild(ulSuggestionsList); 3887 3888 //bouton Rechercher 3889 var SearchButtonAttribute = [ 3890 ['title', 'Rechercher'], 3891 ['id', 'MapControl-itinerary-search-button'], 3892 ['class', 'MapControl-itinerary-search-button'], 3893 ], 3894 SearchButton = domCreateElement('button', SearchButtonAttribute); 3895 SearchButton.innerHTML = options.SearchButtonContent || 'Rechercher'; 3896 SearchButton.addEventListener('click', handleQuery, false); 3897 divItinerarySearch.appendChild(SearchButton); 3898 3899 //div layer 3900 var divItineraryLayerAttribute = [ 3901 ['id', 'MapControl-itinerary-layer'], 3902 ['class', 'MapControl-itinerary-layer'], 3903 ], 3904 divItineraryLayer = domCreateElement('div', divItineraryLayerAttribute); 3905 divItinerary.appendChild(divItineraryLayer); 3906 3907 //label visible 3908 var labelVisibleAttribute = [['for', 'MapControl-itinerary-layer-visible']], 3909 labelVisible = domCreateElement('label', labelVisibleAttribute); 3910 labelVisible.innerHTML = options.labelCheckboxVisible || "Afficher l'itinéraire "; 3911 divItineraryLayer.appendChild(labelVisible); 3912 3913 //checkbox visible 3914 var checkboxLayerAttribute = [ 3915 ['type', 'checkbox'], 3916 ['id', 'MapControl-itinerary-layer-visible'], 3917 ['class', 'MapControl-itinerary-layer-checkbox'], 3918 ['checked', ''], 3919 ], 3920 checkboxLayer = domCreateElement('input', checkboxLayerAttribute); 3921 checkboxLayer.addEventListener('click', handleLayerVisibility, false); 3922 divItineraryLayer.appendChild(checkboxLayer); 3923 3924 //div resume 3925 var divItinerarySummaryAttribute = [ 3926 ['id', 'MapControl-itinerary-summary'], 3927 ['class', 'MapControl-itinerary-summary'], 3928 ], 3929 divItinerarySummary = domCreateElement('div', divItinerarySummaryAttribute); 3930 divItinerary.appendChild(divItinerarySummary); 3931 3932 //div resultats 3933 var divItineraryResultAttribute = [ 3934 ['id', 'MapControl-itinerary-steps'], 3935 ['class', 'MapControl-itinerary-steps'], 3936 ], 3937 divItineraryResult = domCreateElement('div', divItineraryResultAttribute); 3938 divItinerary.appendChild(divItineraryResult); 3939 3940 //div attribution 3941 var divItineraryLicenseAttribute = [ 3942 ['id', 'MapControl-itinerary-license'], 3943 ['class', 'MapControl-itinerary-license'], 3944 ], 3945 divItineraryLicense = domCreateElement('div', divItineraryLicenseAttribute), 3946 attribution = options.attribution || '<a href="http://project-osrm.org">OSRM</a>'; 3947 divItineraryLicense.innerHTML = attribution; 3948 divItinerary.appendChild(divItineraryLicense); 3949 3950 var element = document.createElement('div'); 3951 element.className = 'ol-itinerary ol-unselectable ol-control'; 3952 element.appendChild(controlButton); 3953 element.appendChild(divItinerary); 3954 3955 return element; 3956 }; 3957 3958 ol.control.Control.call(this, { 3959 element: createItineraryView(), 3960 target: options.target, 3961 }); 3962 }; 3963 3964 ol.inherits(app.ItineraryControl, ol.control.Control); 3965} 3966 3967/** 3968 * Enregistrement d'une statistique 3969 * 3970 * @param Date date : date 3971 * @param string type : type d'objet parmis : barreau, lien, repere, evtcplx, lancement et fermeture 3972 * @param string action : nom de l'action parmis : clic, rollover* 3973 * @param string nom : nom de l'objet 3974 * 3975 * @return void 3976 */ 3977function statEnregistrement(date, type, action, nom) { 3978 this.oDate = date; 3979 var sH = this.oDate.getHours().toString(), 3980 sM = this.oDate.getMinutes().toString(), 3981 sS = this.oDate.getSeconds().toString(); 3982 sH = sH.length === 1 ? '0' + sH : sH; 3983 sM = sM.length === 1 ? '0' + sM : sM; 3984 sS = sS.length === 1 ? '0' + sS : sS; 3985 this.sHeure = sH + ':' + sM + ':' + sS; 3986 3987 this.sTypeObjet = type; 3988 this.sAction = action; 3989 this.sNomObjet = nom; 3990} 3991 3992/** 3993 * Dupliquer un enregistrement de statistique 3994 * 3995 * @param object enregistrement : statEnregistrement 3996 * @return object statEnregistrement 3997 */ 3998statEnregistrement.prototype.dupliquer = function (enregistrement) { 3999 return new statEnregistrement( 4000 enregistrement.oDate, 4001 enregistrement.sTypeObjet, 4002 enregistrement.sAction, 4003 enregistrement.sNomObjet 4004 ); 4005}; 4006 4007/** 4008 * Comparer 2 enregistrments enregistrement : un enregistrement de statistique 4009 * 4010 * @param statEnregistrement 4011 * 4012 * @return boolean 4013 */ 4014statEnregistrement.prototype.comparer = function (enregistrement) { 4015 if (enregistrement === null) return false; 4016 if ( 4017 this.sAction === enregistrement.sAction && 4018 this.sTypeObjet === enregistrement.sTypeObjet && 4019 this.sNomObjet === enregistrement.sNomObjet 4020 ) 4021 return true; 4022}; 4023 4024/** 4025 * Serialiser un enregistrement de statistique sous la forme d'une chaine de cacateres : 'heure,type,action,nom' 4026 * 4027 * @return string 4028 */ 4029statEnregistrement.prototype.serialiser = function () { 4030 var serialise = ''; 4031 serialise += this.sHeure + ',' + this.sTypeObjet + ',' + this.sAction + ',' + this.sNomObjet; 4032 return serialise; 4033}; 4034 4035/** 4036 * classe des Statistiques internes 4037 * 4038 * @param string url : url du dossier ou enregistrer le fichier des statistiques 4039 * @param string prefixe : prefixe du nom des fichiers de statistiques 4040 * 4041 * @return statistiqueInterne 4042 */ 4043function statistiqueInterne(url, prefixe) { 4044 this.tStat = []; 4045 this.sUrlDossier = url; 4046 this.sPrefixeFichier = prefixe; 4047 4048 this.oEnregPrecedent = null;
4049 this.nDelaiEnvoi = 5000; // en millisecondes 4050 4051 this.remplirTableauStat('lancement', '', ''); 4052 4053 var _this = this; 4054 setInterval(function () { 4055 _this.envoyerStatistiques(); 4056 }, this.nDelaiEnvoi); 4057} 4058 4059/** 4060 * Remplir le tableau des statistiques 4061 * 4062 * @param string type : type d'objet parmis : barreau, lien, repere, evtcplx, lancement et fermeture 4063 * @param string action : nom de l'action parmis : clic, rollover* 4064 * @param string nom : nom de l'objet 4065 * 4066 * @return void 4067 */ 4068statistiqueInterne.prototype.remplirTableauStat = function (type, action, nom) { 4069 var oNewEnregistrement = new statEnregistrement(new Date(), type, action, nom); 4070 if (!oNewEnregistrement.comparer(this.oEnregPrecedent)) { 4071 this.tStat.push(oNewEnregistrement); 4072 this.oEnregPrecedent = oNewEnregistrement.dupliquer(oNewEnregistrement); 4073 } 4074}; 4075 4076/** 4077 * serialiser le tableau des statistiques avec le séparateur d'enregistrement '|' 4078 * 4079 * @return void 4080 */ 4081statistiqueInterne.prototype.serialiserStatistiques = function () { 4082 var serialise = ''; 4083 for (var i = 0; i < this.tStat.length; i++) { 4084 serialise += this.tStat[i].serialiser() + '|'; 4085 } 4086 4087 return serialise.substr(0, serialise.length - 1); 4088}; 4089 4090/** 4091 * Enregistrer les statistiques en intranet (AJAX) 4092 * 4093 * @param string stat : tableau des statisques sous format d'une chaine de caracteres 4094 * @param stringurlDossier : url du dossier d'enregeidtrement du fichier des statistiques 4095 * @param string prefixeFichier : prefixe du fichier des statistiques 4096 * 4097 * @return void 4098 */ 4099statistiqueInterne.prototype.enregistrerStatistiques = function (stat, urlDossier, prefixeFichier) { 4100 var param = new Object(); 4101 param.statistique = stat; 4102 if (urlDossier != '') param.url_dossier = urlDossier; 4103 if (prefixeFichier != '') param.prefixe_fichier = prefixeFichier; 4104 $.post('mod_turbolead/mod/inforoute/stat-ajax.php', param, this.retourEnregistrement, 'json'); 4105}; 4106 4107/** 4108 * Retour d'Enregistrement des statistiques en intranet (AJAX) 4109 * 4110 * @return void 4111 */ 4112statistiqueInterne.prototype.retourEnregistrement = function (o) {}; 4113 4114/** 4115 * Envoyer les statistiques en AJAX 4116 * 4117 * @return void 4118 */ 4119statistiqueInterne.prototype.envoyerStatistiques = function () { 4120 if (this.tStat.length > 0) { 4121 var sStatistiques = this.serialiserStatistiques(); 4122 this.enregistrerStatistiques(sStatistiques, this.sUrlDossier, this.sPrefixeFichier); 4123 this.tStat = []; 4124 } 4125}; 4126 4127/** 4128 * Gestion des intercations (survol et clique) pour les statistiques internes 4129 * 4130 * @param object evt : evenement singleclick ou pointermove 4131 * @param object _this: objet statistiqueInterne 4132 * 4133 * @return void 4134 */ 4135function handleFeatureInteractionForStatistiqueInterne(evt, _this) { 4136 var pixel = oMap.getEventPixel(evt.originalEvent); 4137 hit = oMap.forEachFeatureAtPixel( 4138 pixel, 4139 function (feature, layer) { 4140 var sStatAction = evt.type === 'singleclick' ? 'clic' : 'rollover', 4141 sStatName = feature.get('titre'), 4142 sStatId = feature.getId(), 4143 sStatType = null, 4144 sFeatureType = feature.get('type'); 4145 4146 //cas des cluster 4147 if (sStatId === undefined && sFeatureType === undefined) { 4148 var tFeature = feature.get('features'); 4149 if (tFeature !== undefined && typeof tFeature[0] !== 'undefined' && tFeature.length === 1) { 4150 sStatName = tFeature[0].get('titre'); 4151 sStatId = tFeature[0].getId(); 4152 sFeatureType = tFeature[0].get('type'); 4153 } 4154 } 4155 4156 if (sStatId !== undefined && sFeatureType !== undefined) { 4157 if (sFeatureType.substr(0, 8) === '_BARREAU') { 4158 sStatType = 'barreau'; 4159 } else if (sFeatureType.substr(0, 7) === '_REPERE') { 4160 sStatType = 'repere'; 4161 } else { 4162 switch (sFeatureType) { 4163 case '_LIEN': 4164 sStatType = 'lien'; 4165 sStatId = sStatName; 4166 break; 4167 case '_BARREAU': 4168 sStatType = 'barreau'; 4169 break; 4170 case '_ZONE': 4171 sStatType = 'barreau'; 4172 break; 4173 case '_DEVIATION': 4174 sStatType = 'evtcplx'; 4175 sStatId = sStatName; 4176 break; 4177 case '_REPERE': 4178 sStatType = 'repere'; 4179 break; 4180 } 4181 } 4182 4183 if (sStatType !== null) { 4184 _this.remplirTableauStat(sStatType, sStatAction, sStatId); 4185 } 4186 } 4187 4188 return true; 4189 }, 4190 _this, 4191 function (layer) { 4192 return DDELayerFilter(layer); 4193 } 4194 ); 4195} 4196 4197/** 4198 * 4199 * partager sur les reseaux sociaux 4200 * 4201 * @param {string} nameSocialMedia : nom du réseau social (facebook ou twitter) 4202 * @param {string|null} url : adresse url a partager, si valeur vide|null: url de la page actuelle (window.location.href) 4203 * @param {string|integer|null}
4203 idRepere : identifiant du repere 4204 * @param {number|null} width : largeur de la fenete ouverte 4205 * @param {number|null} height : hauteur de la fenetre ouverte 4206 * 4207 * @return {boolean} 4208 */ 4209function shareSocialMedia(nameSocialMedia, url, idRepere, width, height) { 4210 var sUrl = '', 4211 sLocation = url !== '' && url !== null ? url : window.location.href, 4212 nWidth = width != null ? width : 400, 4213 nHeight = height != null ? height : 300, 4214 nLeft = screen.width / 2 - nWidth / 2, 4215 nTop = screen.height / 2 - nHeight / 2, 4216 sOption = 4217 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=' + 4218 nWidth + 4219 ',height=' + 4220 nHeight + 4221 ',top=' + 4222 nTop + 4223 ',left=' + 4224 nLeft; 4225 4226 switch (nameSocialMedia) { 4227 case 'facebook': 4228 sUrl = 'https://www.facebook.com/sharer/sharer.php'; 4229 sUrl += '?u=' + encodeURIComponent(sLocation); 4230 window.open(sUrl, '_blank', sOption); 4231 return true; 4232 case 'google+': //https://developers.google.com/+/web/share/#sharelink 4233 sUrl = 'https://plus.google.com/share'; 4234 sUrl += '?url=' + encodeURIComponent(sLocation); 4235 window.open(sUrl, '_blank', sOption); 4236 return true; 4237 case 'twitter': //https://dev.twitter.com/web/tweet-button/web-intent 4238 var sText = '', 4239 iTextLength = 139 - Math.min(sLocation.length, 23), 4240 sTitre = '', 4241 sDescription = '', 4242 oRepere = getRepereById(idRepere); 4243 4244 if (oRepere) { 4245 sTitre = oRepere.get('titre'); 4246 sDescription = oRepere.get('description'); 4247 } 4248 4249 sUrl = 'https://twitter.com/intent/tweet'; 4250 4251 sText += sTitre !== undefined && sTitre !== '' ? sTitre : ''; 4252 sText += 4253 sTitre !== undefined && sTitre !== '' && sDescription !== undefined && sDescription !== '' ? ': ' : ''; 4254 sText += sDescription !== undefined && sDescription !== '' ? sDescription : ''; 4255 sText = sText.substr(0, iTextLength); 4256 4257 sUrl += '?url=' + encodeURITwitter(sLocation); 4258 if (sText !== '') sUrl += '&text=' + encodeURITwitter(sText); 4259 4260 window.open(sUrl, '_blank', sOption); 4261 return true; 4262 } 4263 return false; 4264} 4265 4266/** 4267 * Encodage URI pour twitter 4268 * 4269 * @param {string} : chaine a converir 4270 * 4271 * @return {string} 4272 */ 4273function encodeURITwitter(str) { 4274 return encodeURIComponent(str) 4275 .replace(/!/g, '%21') 4276 .replace(/'/g, '%27') 4277 .replace(/\(/g, '%28') 4278 .replace(/\)/g, '%29') 4279 .replace(/\*/g, '%2A') 4280 .replace(/%20/g, '+') 4281 .replace(/~/g, '%7E'); 4282} 4283 4284/** 4285 * Retourner la résolution correspondante à la valeur du zoom en entrée 4286 * 4287 * @param {inetger} zoom : valeur du zoom à convertir 4288 * 4289 * @return float|undefined 4290 */ 4291function getResolutionOfZoom(zoom) { 4292 var tResolution = [ 4293 156543.03392804097, 78271.51696402048, 39135.75848201024, 19567.87924100512, 9783.93962050256, 4891.96981025128, 4294 2445.98490512564, 1222.99245256282, 611.49622628141, 305.748113140705, 152.8740565703525, 76.43702828517625, 4295 38.21851414258813, 19.109257071294063, 9.554628535647032, 4.777314267823516, 2.388657133911758, 4296 1.194328566955879, 0.5971642834779395, 0.29858214173896974, 0.14929107086948487, 0.07464553543474244, 4297 0.03732276771737122, 0.01866138385868561, 0.009330691929342804, 0.004665345964671402, 0.002332672982335701, 4298 0.0011663364911678506, 0.0005831682455839253, 4299 ]; 4300 if (zoom === parseInt(zoom, 10) && zoom >= 0 && zoom <= 28) return tResolution[zoom]; 4301 return undefined; 4302} 4303 4304/** 4305 * Assigner la resolution de la vue avec animation 4306 * 4307 * @param {float} resolution : resolution de la vue 4308 * 4309 * @return void 4310 */ 4311function setViewResolutionWithAnimation(resolution) { 4312 // zoom à partir de la resolution courante 4313 var zoom = ol.animation.zoom({ 4314 resolution: oMap.getView().getResolution(), 4315 });
4316 oMap.beforeRender(zoom); 4317 oMap.getView().setResolution(resolution); 4318} 4319 4320/** 4321 * Assigner la resolution (avec un facteur) de la vue avec animation 4322 * 4323 * @param {float} factor : facteur de modification de la resolution de la vue (zoom+1=> factor=0.5, zoom-1=>factor=2) 4324 * 4325 * @return void 4326 */ 4327function setViewResolutionFactorWithAnimation(factor) { 4328 // zoom à partir de la resolution courante 4329 var zoom = ol.animation.zoom({ 4330 resolution: oMap.getView().getResolution(), 4331 }); 4332 oMap.beforeRender(zoom); 4333 oMap.getView().setResolution(oMap.getView().getResolution() * factor); 4334} 4335 4336/** 4337 * Assigner le zoom de la vue avec animation 4338 * 4339 * @param {integer} zoom : zoom de la vue 4340 * 4341 * @return void 4342 */ 4343function setViewZoomWithAnimation(zoom) { 4344 var resolution = getResolutionOfZoom(zoom); 4345 if (resolution !== undefined) setViewResolutionWithAnimation(resolution); 4346} 4347 4348/** 4349 * Assigner les coordonnées du centre de la vue avec animation 4350 * 4351 * @param {float[]} location : vecteur des coordonnées du centre de la vue 4352 * 4353 * @return void 4354 */ 4355function setViewCenterWithAnimation(location) { 4356 // pan à partir du centre courant 4357 var pan = ol.animation.pan({ 4358 source: oMap.getView().getCenter(), 4359 }); 4360 oMap.beforeRender(pan); 4361 oMap.getView().setCenter(location); 4362} 4363 4364/** 4365 * Gérer une interaction (clic ou survol) sur cluster 4366 * 4367 * @param {object} evt 4368 * 4369 * @return boolean 4370 */ 4371function manageClusterInteraction(evt) { 4372 var pixel = oMap.getEventPixel(evt.originalEvent); 4373 var cluster = oMap.forEachFeatureAtPixel( 4374 pixel, 4375 function (feature, layer) { 4376 var tFeature = feature.get('features'); 4377 if (tFeature !== undefined && tFeature.length !== 1) return feature; 4378 return false; 4379 }, 4380 null, 4381 function (layer) { 4382 return DDELayerFilter(layer); 4383 } 4384 ); 4385 4386 if (cluster) { 4387 var tCoordinate = cluster.getGeometry().getCoordinates(), 4388 nZoom = oMap.getView().getZoom(); 4389 if (nZoom !== undefined) setViewZoomAndCenter(nZoom + 1, tCoordinate[0], tCoordinate[1], defaultOsmProjection); 4390 return true; 4391 } 4392 4393 return false; 4394} 4395 4396/** 4397 * Mettre à jour le ou les calques des repere à une date précise 4398 * 4399 * @parm {string} date : date de mise à jour du calque des reperes sous le format : timestamp|timestamp ou timestamp 4400 * 4401 * @return boolean 4402 */ 4403function updateLayerRepereAtDate(date) { 4404 var layerConfig = getLayerConfig('repere'), 4405 option = getLayerConfiguration(layerConfig); 4406 4407 if (layerConfig !== undefined && layerConfig.name === 'layer-repere' && option !== null) { 4408 option.date = date; 4409 DDEAddSpecialLayer(option); 4410 return true; 4411 } 4412 4413 return false; 4414} 4415 4416/** 4417 * Afficher le calque en entree et cacher les autres calques ( a sauvegader) sauf les calques: 'group-tiles', 'layer-fond', 'layer-outline' et 'layer-link' 4418 * si le calque est visible afficher les calques sauvegadés 4419 * 4420 * @param {string} layerName : nom du calque à afficher 4421 * 4422 * @return boolean 4423 */ 4424function toggleDisplayThisLayer(layerName) { 4425 var targetLayer = getLayerByName(layerName); 4426 4427 if (targetLayer !== null) { 4428 var targetLayerVisibility = !targetLayer.getVisible(); 4429 4430 // change visility of target layer 4431 targetLayer.setVisible(targetLayerVisibility); 4432 if (targetLayerVisibility) { 4433 //target layer : visible 4434 var allwaysVisibleLayers = ['group-tiles', 'layer-fond', 'layer-outline', 'layer-link']; 4435 allwaysVisibleLayers.push(layerName); 4436 visibleLayers = []; 4437 oMap.getLayers().forEach(function (lyr) { 4438 if (typeof lyr === 'object') { 4439 var currentLayerName = lyr.get('name'), 4440 currentLayerVisibility = lyr.getVisible(); 4441 4442 if (allwaysVisibleLayers.indexOf(currentLayerName) === -1 && currentLayerVisibility === true) { 4443 //other layers 4444 lyr.setVisible(false); 4445 setElementAttribute("[data-layer='" + currentLayerName + "']", 'aria-pressed', 'false'); 4446 visibleLayers.push(currentLayerName); 4447 } 4448 } 4449 }); 4450 } else { 4451 //target layer : invisible 4452 if (typeof visibleLayers !== 'undefined' && visibleLayers.length > 0) { 4453 for (var i = 0; i < visibleLayers.length; i++) { 4454 var currentLayer = getLayerByName(visibleLayers[i]); 4455 if (currentLayer !== null) { 4456 currentLayer.setVisible(true); 4457 setElementAttribute("[data-layer='" + visibleLayers[i] + "']", 'aria-pressed', 'true'); 4458 } 4459 } 4460 4461 //empty visibleLayers 4462 visibleLayers.length = 0; 4463 } 4464 } 4465 4466 return true; 4467 } 4468 4469 return false; 4470} 4471 4472/** 4473 * Afficher exclusivement la liste des calques en entrée et masquer le reste des calques sauf les calques visibles par défaut: 'group-tiles', 'layer-fond', 'layer-outline' et 'layer-link' 4474 * 4475 * @param {string[]} : tableau des noms des calques à afficher 4476 * 4477 * @return boolean : affichage ou pas d'au moins un calque 4478 */ 4479function displayOnlyTheseLayers(layers) { 4480 var bModif = false; 4481 if (layers instanceof Array) { 4482 var defaultVisibleLayers = ['group-tiles', 'layer-fond', 'layer-outline', 'layer-link'], 4483 visibleLayers = defaultVisibleLayers.concat(layers); 4484
4485 oMap.getLayers().forEach(function (lyr) { 4486 if (typeof lyr === 'object') { 4487 var currentlayer = lyr.get('name'); 4488 4489 if (visibleLayers.indexOf(currentlayer) === -1) { 4490 lyr.setVisible(false); 4491 setElementAttribute("[data-layer='" + currentlayer + "']", 'aria-pressed', 'false'); 4492 } else { 4493 lyr.setVisible(true); 4494 setElementAttribute("[data-layer='" + currentlayer + "']", 'aria-pressed', 'true'); 4495 bModif = true; 4496 } 4497 } 4498 }); 4499 } 4500 4501 return bModif; 4502} 4503 4504/** 4505 * initilaiser l'attribut d'un élement 4506 * 4507 * @param {string} selectorName : nom du selecteur (document.querySelector) 4508 * @param {string} attribute : nom de l'attribut à modifier 4509 * @param {string} value : valeur de l'attribut 4510 * 4511 * @return boolean 4512 */ 4513function setElementAttribute(selectorName, attribute, value) { 4514 var element = document.querySelector(selectorName); 4515 if (element !== null && element.hasAttribute(attribute)) { 4516 element.setAttribute(attribute, value); 4517 return true; 4518 } 4519 4520 return false; 4521} 4522 4523/** 4524 * Afficher la listes des features sous forme d'une table HTML 4525 * 4526 * @param {ol.Feature[]} features : tables des feature 4527 * @param {string} tableId : identifiant de la table 4528 * 4529 * @return void 4530 */ 4531function displayFeaturesInHtmlTable(features, tableId) { 4532 var oTable = document.getElementById(tableId); 4533 if (oTable !== null) { 4534 oTable = oTable.getElementsByTagName('tbody')[0]; 4535 } 4536 if (features !== null && oTable !== null) { 4537 //delete old rows 4538 deleteHtmlTableRow(tableId); 4539 4540 //insert new rows 4541 for (var i = 0; i < features.length; i++) { 4542 var oFeature = features[i], 4543 row = oTable.insertRow(i), 4544 cell1 = row.insertCell(0), 4545 cell2 = row.insertCell(1), 4546 cell3 = row.insertCell(2); 4547 4548 cell1.innerHTML = 4549 '<img src="' + oFeature.get('url_icone') + '" class="calendarIcone">'; 4550 cell2.innerHTML = '<p class="calendarTitre">' + oFeature.get('titre') + '</p>'; 4551 cell3.innerHTML = '<p class="calendarDescription">' + oFeature.get('description') + '</p>'; 4552 } 4553 } 4554} 4555 4556/** 4557 * Suppression de toutes les lignes d'une table HTML sauf la premiere (titre) 4558 * 4559 * @param {string} tableId : identifiant de la table 4560 * 4561 * @return void 4562 */ 4563function deleteHtmlTableRow(tableId) { 4564 var oTable = document.getElementById(tableId); 4565 if (oTable !== null) { 4566 var iRowCount = oTable.rows.length, 4567 iRowIndex = 1; 4568 for (var i = iRowIndex; i < iRowCount; i++) { 4569 oTable.deleteRow(iRowIndex); 4570 } 4571 } 4572} 4573 4574/** 4575 * Met à jour le tableau des évènements visibles 4576 */ 4577function ddeOpenLayersMapUpdateFeaturesTable() { 4578 var visibleFeatures = []; 4579 if ( 4580 layerConfig.repere.featureDisplayContainerId !== undefined && 4581 layerConfig.repere.featureDisplayContainerId !== '' 4582 ) { 4583 // Récupère les calques des repères 4584 var repereLayers = getAllRepereLayer(); 4585 4586 // Récupère les éléments des calques visibles 4587 for (var layerIndex = 0; layerIndex < repereLayers.length; layerIndex++) { 4588 // Récupère le calque 4589 var repereLayer = getLayerByName(repereLayers[layerIndex]); 4590 4591 // Récupère les éléments 4592 if (!repereLayer.getVisible()) { 4593 continue; 4594 } 4595 4596 // Récupère la source 4597 var layerSource = repereLayer.getSource(); 4598 if (layerSource instanceof ol.source.Cluster) { 4599 layerSource = layerSource.getSource(); 4600 } 4601 4602 // Ajoute les éléments à la liste 4603 var layerFeatures = layerSource.getFeatures(); 4604 for (var featureIndex = 0; featureIndex < layerFeatures.length; featureIndex++) { 4605 visibleFeatures.push(layerFeatures[featureIndex]); 4606 } 4607 } 4608 4609 // Remplit le tableau 4610 displayFeaturesInHtmlTable(visibleFeatures, layerConfig.repere.featureDisplayContainerId); 4611 } 4612} 4613 4614/** 4615 * teste si l'événement et dans sa periodede récurrence ou pas 4616 * si oui il sera affiché, non sinon 4617 * @param recurrence 4618 * @returns 4619 */ 4620function DDETestRecurrence(recurrence) { 4621 var today = new Date(); 4622 var nToday = today.getUTCDay(); 4623 4624 var hToday = today.getUTCHours(); 4625 var sH = hToday.toString(); 4626 if (hToday < 10) { 4627 sH = '0' + sH; 4628 } 4629 var mToday = today.getUTCMinutes(); 4630 var sM = mToday.toString(); 4631 if (mToday < 10) { 4632 sM = '0' + mToday.toString(); 4633 } 4634 var sHM = sH + ':' + sM; 4635 4636 if (!recurrence['next_day']) { 4637 // l'événement est sur la même journée => on la journée puis les heurs 4638 if (recurrence['jours_recurrence'][nToday]) { 4639 if (sHM >
4639= recurrence['heure_recurrence_debut'] && sHM <= recurrence['heure_recurrence_fin']) { 4640 return true; 4641 } 4642 } 4643 } else { 4644 // l'evenement s'étale sur deux jours => on verifie pour la veille, le jour meme 4645 var day0 = (nToday - 1) % 7; 4646 var day1 = nToday; 4647 4648 // l'évenement a commencé la veille et n'est pas encore fini 4649 if (recurrence['jours_recurrence'][day0] && sHM <= recurrence['heure_recurrence_fin']) { 4650 return true; 4651 } 4652 4653 // l'evénement commence aujourd'hui et ce termine demain 4654 if (recurrence['jours_recurrence'][day1] && sHM >= recurrence['heure_recurrence_debut']) { 4655 return true; 4656 } 4657 } 4658 return false; 4659}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.