2024-12-11 17:32:48 +01:00
/ * *
* rechercher les bornes de recharge ,
* afficher des cercles colorés selon la puissance max de la station
* lister les bornes trouvées dans la page
* @ type { boolean }
* /
2024-12-31 22:56:45 +01:00
import lcm _config from './lcm_config.js'
2025-05-01 12:50:37 +02:00
import lcm _utils , { valid _qa _message } from './lcm_utils.js'
2024-12-31 22:56:45 +01:00
import lcm _color _utils from './lcm_color_utils.js'
2025-04-18 16:50:26 +02:00
import { sendToJOSM , createJOSMEditLink } from './lcm_editor.js'
2025-04-28 16:50:25 +02:00
2024-12-23 00:26:13 +01:00
let geojsondata ;
let lastLatLng ;
2025-04-18 17:53:07 +02:00
let searchLocationMarker = null ;
2025-04-27 21:47:38 +02:00
let count _hidden _by _filters = 0 ;
2025-05-01 12:28:43 +02:00
let averageChargeKwh = 26 ;
2025-04-18 17:53:07 +02:00
2024-12-22 23:39:17 +01:00
2024-10-17 15:01:47 +02:00
// serveurs de tuiles: https://wiki.openstreetmap.org/wiki/Tile_servers
// https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png
// https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png
2024-10-18 00:47:01 +02:00
// https://tile.openstreetmap.org/{z}/{x}/{y}.png
// 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'
2024-12-22 23:39:17 +01:00
2024-10-17 15:01:47 +02:00
// Créer la carte centrée sur Rouen
2024-12-14 17:39:17 +01:00
// Liste des 20 villes les plus peuplées de France avec leurs coordonnées géographiques
2024-12-17 11:53:02 +01:00
2024-12-14 17:39:17 +01:00
// Initialisation de la carte avec la vue centrée sur la ville choisie
2024-12-18 13:40:58 +01:00
let map = L . map ( 'map' )
L . control . scale ( ) . addTo ( map )
2024-12-16 12:54:15 +01:00
2024-12-22 00:02:33 +01:00
/ * *
* filtres à toggle par des boutons dans la page
* à appliquer à chaque rafraîchissement des points geojson
* TODO : make buttons and filter in refresh circles
* /
2024-12-22 23:39:17 +01:00
let filterStatesAvailable = [ 'hide' , 'show' , 'showOnly' ]
2024-12-31 22:56:45 +01:00
let filters _features = {
2025-02-03 13:41:48 +01:00
display _unknown _max _power _station : filterStatesAvailable [ 1 ]
2024-12-31 22:56:45 +01:00
}
2024-12-22 00:02:33 +01:00
let display _type2 _sockets = 'show' ;
let display _type2 _combo _sockets = 'show' ;
let display _unknown _max _power _station = 'show' ;
2025-02-03 10:49:43 +01:00
let display _alert _cable _missing = 'show' ;
2024-12-22 00:02:33 +01:00
let display _known _max _power _station = 'show' ;
let display _type2 _combo _sockets _with _cable = 'show' ;
let display _lower _than _50kw = 'show' ;
let display _higer _than _50kw = 'show' ;
let display _lower _than _200kw = 'show' ;
let display _higer _than _200kw = 'show' ;
let display _chelou = 'show' ; // les stations avec une valeur suspecte, plus de 400kW
2025-04-18 17:53:07 +02:00
// Ajouter cette fonction avant searchLocation
function moveToLocation ( place ) {
const lat = parseFloat ( place . lat ) ;
const lon = parseFloat ( place . lon ) ;
if ( isNaN ( lat ) || isNaN ( lon ) ) {
console . error ( 'Coordonnées invalides:' , place ) ;
return ;
}
// Supprimer l'ancien marqueur s'il existe
if ( searchLocationMarker ) {
map . removeLayer ( searchLocationMarker ) ;
}
// Créer un nouveau marqueur avec une icône personnalisée
searchLocationMarker = L . marker ( [ lat , lon ] , {
icon : L . divIcon ( {
className : 'search-location-marker' ,
html : '📍' ,
iconSize : [ 30 , 30 ] ,
iconAnchor : [ 15 , 30 ]
} )
} ) ;
// Ajouter un popup avec le nom du lieu
const popupContent = `
< strong > $ { place . display _name } < / s t r o n g >
$ { place . type ? ` <br>Type: ${ place . type } ` : '' }
$ { place . context ? ` <br> ${ place . context } ` : '' }
` ;
searchLocationMarker . bindPopup ( popupContent ) ;
// Ajouter le marqueur à la carte
searchLocationMarker . addTo ( map ) ;
2025-04-28 11:20:11 +02:00
// Désactiver temporairement l'événement moveend
map . off ( 'moveend' , onMapMoveEnd ) ;
2025-04-18 17:53:07 +02:00
// Centrer la carte sur le lieu
map . setView ( [ lat , lon ] , map . getZoom ( ) ) ;
2025-04-28 11:20:11 +02:00
// Réactiver l'événement moveend après un court délai
setTimeout ( ( ) => {
map . on ( 'moveend' , onMapMoveEnd ) ;
} , 500 ) ;
2025-04-18 17:53:07 +02:00
// Ouvrir le popup automatiquement
searchLocationMarker . openPopup ( ) ;
}
// Déplacer searchLocationWithAddok avant searchLocation
function searchLocationWithAddok ( searchText , mapCenter ) {
const baseUrl = 'https://demo.addok.xyz/search' ;
const params = new URLSearchParams ( {
q : searchText ,
limit : 10 ,
lat : mapCenter . lat ,
lon : mapCenter . lng
} ) ;
const url = ` ${ baseUrl } ? ${ params . toString ( ) } ` ;
return fetch ( url )
. then ( response => {
if ( ! response . ok ) {
throw new Error ( 'Erreur réseau lors de la recherche' ) ;
}
return response . json ( ) ;
} )
. then ( data => {
if ( ! data . features || data . features . length === 0 ) {
throw new Error ( 'Aucun résultat trouvé' ) ;
}
return data . features . map ( feature => ( {
lat : feature . geometry . coordinates [ 1 ] ,
lon : feature . geometry . coordinates [ 0 ] ,
display _name : feature . properties . label ,
importance : feature . properties . score ,
context : feature . properties . context ,
type : feature . properties . type ,
city : feature . properties . city ,
distance : feature . properties . distance
} ) ) ;
} ) ;
}
// Modifier la fonction searchLocation
function searchLocation ( ) {
const location = $ ( '#searchLocation' ) . val ( ) ;
if ( ! location ) {
alert ( 'Veuillez entrer un lieu à rechercher.' ) ;
return ;
}
const useAddok = $ ( '#useAddok' ) . is ( ':checked' ) ;
const searchPromise = useAddok
? searchLocationWithAddok ( location , map . getCenter ( ) )
: fetch ( ` https://nominatim.openstreetmap.org/search?format=json&q= ${ encodeURIComponent ( location ) } ` )
. then ( response => response . json ( ) ) ;
searchPromise
. then ( data => {
const resultsDropdown = $ ( '#searchResults' ) ;
resultsDropdown . empty ( ) ;
if ( ! data || data . length === 0 ) {
alert ( 'Lieu non trouvé. Veuillez essayer un autre terme de recherche.' ) ;
resultsDropdown . hide ( ) ;
return ;
}
// Toujours sélectionner le premier résultat
moveToLocation ( data [ 0 ] ) ;
2025-05-01 12:38:48 +02:00
displayPointsFromApi ( ) ;
2025-04-18 17:53:07 +02:00
// Si il y a plus d'un résultat, les afficher quand même dans la liste
if ( data . length > 1 ) {
2025-04-28 11:20:11 +02:00
// Vérifier si le bouton de fermeture existe déjà
if ( $ ( '.close-results-button' ) . length === 0 ) {
const closeButton = $ ( '<button>' )
. addClass ( 'close-results-button' )
. html ( '❌' )
. attr ( 'title' , 'Fermer les résultats de recherche' )
. on ( 'click' , function ( ) {
$ ( '#searchResults' ) . hide ( ) ;
$ ( this ) . hide ( ) ;
$ ( '#searchLocation' ) . val ( '' ) . focus ( ) ;
} ) ;
2025-04-18 17:53:07 +02:00
2025-04-28 11:20:11 +02:00
resultsDropdown . before ( closeButton ) ;
}
2025-04-18 17:53:07 +02:00
data . forEach ( ( place , index ) => {
let displayText = place . display _name ;
if ( useAddok && place . distance ) {
displayText += ` ( ${ Math . round ( place . distance ) } m) ` ;
}
const option = $ ( '<option></option>' )
. val ( index )
. text ( displayText )
. data ( 'place' , place ) ;
resultsDropdown . append ( option ) ;
} ) ;
resultsDropdown . show ( ) ;
2025-04-28 11:20:11 +02:00
$ ( '.close-results-button' ) . show ( ) ;
2025-04-18 17:53:07 +02:00
// Sélectionner visuellement le premier résultat dans la liste
resultsDropdown . val ( 0 ) ;
} else {
resultsDropdown . hide ( ) ;
}
} )
. catch ( error => {
console . error ( 'Erreur lors de la recherche du lieu :' , error ) ;
alert ( 'Erreur lors de la recherche du lieu : ' + error . message ) ;
} ) ;
}
2024-12-22 00:02:33 +01:00
function setRandomView ( ) {
2024-12-31 22:56:45 +01:00
let randomCity = lcm _utils . cities [ Math . floor ( Math . random ( ) * lcm _utils . cities . length ) ] ;
map = map . setView ( randomCity . coords , lcm _config . initialZoom ) ;
2024-12-16 12:54:15 +01:00
}
2024-12-18 13:40:58 +01:00
2024-12-22 00:02:33 +01:00
function setCoordinatesOfLeafletMapFromQueryParameters ( ) {
2024-12-28 17:59:15 +01:00
const urlParams = new URLSearchParams ( window . location . href ) ;
const lat = urlParams . get ( 'lat' ) ;
const lng = urlParams . get ( 'lng' ) ;
const zoom = urlParams . get ( 'zoom' ) ;
2024-12-22 00:02:33 +01:00
if ( lat && lng && zoom ) {
2024-12-28 17:59:15 +01:00
map = map . setView ( [ lat , lng ] , zoom ) ;
2024-12-22 00:02:33 +01:00
} else {
2024-12-28 17:59:15 +01:00
console . error ( 'Les paramètres de coordonnées et de zoom doivent être présents dans l\'URL.' ) ;
setRandomView ( ) ;
2024-12-22 00:02:33 +01:00
}
2024-12-16 12:54:15 +01:00
}
2024-12-22 00:02:33 +01:00
function updateURLWithMapCoordinatesAndZoom ( ) {
// Récupère les coordonnées et le niveau de zoom de la carte
const center = map . getCenter ( )
const zoom = map . getZoom ( )
2024-12-16 12:54:15 +01:00
2024-12-22 00:02:33 +01:00
// Construit l'URL avec les paramètres de coordonnées et de zoom
const url = ` #coords=1&lat= ${ center . lat } &lng= ${ center . lng } &zoom= ${ zoom } `
// Met à jour l'URL de la page
history . replaceState ( null , null , url )
2025-02-03 10:49:43 +01:00
updateExternalEditorsLinks ( )
2024-12-16 12:54:15 +01:00
}
2024-12-28 17:00:21 +01:00
2025-04-28 11:20:11 +02:00
let all _stations _markers = L . layerGroup ( ) . addTo ( map ) // layer group pour tous les marqueurs
2025-04-28 15:49:55 +02:00
let bad _tags _markers = L . layerGroup ( ) // layer group pour les marqueurs avec des problèmes de qualité
2024-12-28 17:00:21 +01:00
// let stations_much_speed_wow = L.layerGroup().addTo(map) // layer group des stations rapides
2024-12-31 22:56:45 +01:00
var osm = L . tileLayer ( lcm _config . tileServers . osm , {
attribution : lcm _config . osmMention + '© <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors'
2024-12-14 18:00:09 +01:00
} )
2024-12-31 22:56:45 +01:00
var cycle = L . tileLayer ( lcm _config . tileServers . cycle , {
attribution : lcm _config . osmMention + '© <a href="https://www.opencyclemap.org/">OpenCycleMap</a> contributors'
2024-12-14 18:00:09 +01:00
} )
2024-12-31 22:56:45 +01:00
var transport = L . tileLayer ( lcm _config . tileServers . transport , {
attribution : lcm _config . osmMention
2024-12-14 18:00:09 +01:00
} )
let tileGrey =
2024-12-31 22:56:45 +01:00
L . tileLayer ( lcm _config . tileServers . cartodb , {
attribution : lcm _config . osmMention
2024-12-22 00:02:33 +01:00
} )
2024-12-14 18:00:09 +01:00
let stamen =
2024-12-31 22:56:45 +01:00
L . tileLayer ( lcm _config . tileServers . stamen , {
attribution : lcm _config . osmMention
2024-12-22 00:02:33 +01:00
} )
2025-04-18 17:53:07 +02:00
// Ajouter après les autres déclarations de tileLayer
let bdortho = L . tileLayer ( 'https://wxs.ign.fr/ortho/geoportail/wmts?' +
'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTHOIMAGERY.ORTHOPHOTOS' +
'&STYLE=normal&FORMAT=image/jpeg&TILEMATRIXSET=PM&' +
'TILEMATRIX={z}&TILEROW={y}&TILECOL={x}' , {
attribution : '© <a href="https://geoservices.ign.fr/bdortho">IGN-F/Géoportail</a>' ,
maxZoom : 19
} ) ;
// Modifier la définition de baseLayers pour inclure la BD ORTHO
2024-12-14 18:00:09 +01:00
var baseLayers = {
2024-12-22 00:02:33 +01:00
'Grey' : tileGrey ,
2025-04-28 11:20:11 +02:00
// 'Stamen': stamen,
2024-12-22 00:02:33 +01:00
'OpenStreetMap' : osm ,
2025-04-28 11:20:11 +02:00
// 'BD ORTHO IGN': bdortho,
2024-12-22 00:02:33 +01:00
// 'OpenCycleMap': cycle,
'Transport' : transport
2024-12-14 18:00:09 +01:00
}
2024-12-14 18:08:00 +01:00
tileGrey . addTo ( map )
2024-12-11 23:13:15 +01:00
2024-12-28 17:00:21 +01:00
2024-12-22 00:02:33 +01:00
function buildOverpassApiUrl ( map , overpassQuery ) {
2024-12-28 17:59:15 +01:00
let baseUrl = 'https://overpass-api.de/api/interpreter' ;
const kilometersMarginForLoading = 2 ;
const marginInDegrees = kilometersMarginForLoading / 111 ;
const south = map . getBounds ( ) . getSouth ( ) - marginInDegrees ;
const west = map . getBounds ( ) . getWest ( ) - marginInDegrees ;
const north = map . getBounds ( ) . getNorth ( ) + marginInDegrees ;
const east = map . getBounds ( ) . getEast ( ) + marginInDegrees ;
let bounds = south + ',' + west + ',' + north + ',' + east ;
let resultUrl , query = '' ;
2024-10-17 15:01:47 +02:00
2024-12-31 22:56:45 +01:00
if ( lcm _config . overrideQuery ) {
2024-12-22 00:02:33 +01:00
query = ` ?data=[out:json][timeout:15];(
2024-12-21 22:58:50 +01:00
nwr [ amenity = charging _station ] ( $ { bounds } ) ;
2024-12-28 17:59:15 +01:00
) ; out body geom ; ` ;
2024-12-22 00:02:33 +01:00
} else {
2024-12-28 17:59:15 +01:00
let nodeQuery = 'node[' + overpassQuery + '](' + bounds + ');' ;
let wayQuery = 'way[' + overpassQuery + '](' + bounds + ');' ;
let relationQuery = 'relation[' + overpassQuery + '](' + bounds + ');' ;
query = '?data=[out:json][timeout:15];(' + nodeQuery + wayQuery + relationQuery + ');out body geom;' ;
2024-12-22 00:02:33 +01:00
}
2024-12-28 17:59:15 +01:00
resultUrl = baseUrl + query ;
return resultUrl ;
2025-02-03 13:41:48 +01:00
}
2024-12-28 17:59:15 +01:00
2024-10-17 15:01:47 +02:00
2024-12-22 00:02:33 +01:00
function supprimerMarqueurs ( ) {
2024-12-28 17:59:15 +01:00
all _stations _markers . clearLayers ( ) ;
2024-12-22 00:02:33 +01:00
map . eachLayer ( ( layer ) => {
if ( layer instanceof L . Marker ) {
2024-12-28 17:59:15 +01:00
layer . remove ( ) ;
2024-12-22 00:02:33 +01:00
}
2024-12-28 17:59:15 +01:00
} ) ;
2024-10-18 00:33:25 +02:00
}
2024-12-11 23:13:15 +01:00
let coef _reduction _bars = 0.8
2024-10-17 15:01:47 +02:00
2024-12-22 00:02:33 +01:00
function calculerPourcentage ( partie , total , reduc ) {
if ( total === 0 ) {
return 'Division par zéro impossible'
}
let coef _reduction = 1
if ( reduc ) {
coef _reduction = coef _reduction _bars
}
return ( ( partie / total ) * 100 * coef _reduction ) . toFixed ( 1 )
2024-12-11 23:13:15 +01:00
}
2025-04-18 18:00:08 +02:00
// Ajouter une variable globale pour stocker le nombre d'issues Osmose
let osmoseIssuesCount = 0 ;
2025-04-20 00:54:04 +02:00
// Ajouter une variable globale pour stocker le nombre de stations affichées
let displayedStationsCount = 0 ;
2025-04-27 22:05:21 +02:00
function displayStatsFromGeoJson ( resultAsGeojson , stats ) {
2024-12-28 17:59:15 +01:00
let count = resultAsGeojson . features . length ;
let count _station _output = 0 ;
let count _ref _eu = 0 ;
let output _more _than _300 = 0 ;
let output _more _than _200 = 0 ;
let output _more _than _100 = 0 ;
let output _more _than _50 = 0 ;
let count _station _outputoutput _between _1 _and _50 = 0 ;
let count _output _unknown = 0 ;
let count _estimated _type2combo = 0 ;
let count _found _type2combo = 0 ;
let count _found _type2 = 0 ;
2024-12-22 00:02:33 +01:00
2025-04-27 21:47:38 +02:00
// Compter les filtres désactivés
let disabledFilters = 0 ;
Object . keys ( lcm _config . filterConfigs ) . forEach ( filterId => {
if ( ! lcm _config . filterConfigs [ filterId ] ) disabledFilters ++ ;
} ) ;
2025-04-27 22:24:09 +02:00
2025-04-27 22:05:21 +02:00
$ ( '#count_features_fond' ) . html ( '⚡' + count + ' stations' + ( disabledFilters > 0 ? ` ( ${ disabledFilters } filtre ${ disabledFilters > 1 ? 's' : '' } désactivé ${ disabledFilters > 1 ? 's' : '' } , ${ stats . count _hidden _by _filters } masqué ${ stats . count _hidden _by _filters > 1 ? 's' : '' } ) ` : '' ) ) ;
2024-12-31 23:27:19 +01:00
2024-12-22 00:02:33 +01:00
resultAsGeojson . features . map ( feature => {
2024-12-28 17:59:15 +01:00
let found _type2 _combo = false ;
let found _type2 = false ;
let keys _of _object = Object . keys ( feature . properties . tags ) ;
2024-12-22 00:02:33 +01:00
keys _of _object . map ( tagKey => {
if ( tagKey . indexOf ( 'type2_combo' ) !== - 1 ) {
2024-12-28 17:59:15 +01:00
found _type2 _combo = true ;
2024-12-22 00:02:33 +01:00
}
if ( tagKey . indexOf ( 'type2' ) !== - 1 ) {
2024-12-28 17:59:15 +01:00
found _type2 = true ;
2024-12-22 00:02:33 +01:00
}
2024-12-28 17:59:15 +01:00
} ) ;
2024-12-31 22:56:45 +01:00
let outputPower = lcm _utils . guessOutputPowerFromFeature ( feature ) ;
2024-12-22 00:02:33 +01:00
if ( found _type2 _combo ) {
2024-12-28 17:59:15 +01:00
count _found _type2combo ++ ;
2024-12-22 00:02:33 +01:00
}
if ( found _type2 ) {
2024-12-28 17:59:15 +01:00
count _found _type2 ++ ;
2024-12-22 00:02:33 +01:00
}
if ( outputPower == 0 ) {
2024-12-28 17:59:15 +01:00
count _output _unknown ++ ;
2024-12-22 00:02:33 +01:00
}
2024-12-31 22:56:45 +01:00
// filtres
// filtrer les valeurs inconnues
2024-12-22 00:02:33 +01:00
if ( outputPower >= 200 && ! found _type2 _combo ) {
2024-12-28 17:59:15 +01:00
count _estimated _type2combo ++ ;
2024-12-22 00:02:33 +01:00
}
if ( outputPower > 0 && outputPower < 50 ) {
2024-12-28 17:59:15 +01:00
count _station _outputoutput _between _1 _and _50 ++ ;
2024-12-22 00:02:33 +01:00
}
if ( outputPower >= 50 && outputPower < 100 ) {
2024-12-28 17:59:15 +01:00
output _more _than _50 ++ ;
2024-12-22 00:02:33 +01:00
} else if ( outputPower >= 100 && outputPower < 200 ) {
2024-12-28 17:59:15 +01:00
output _more _than _100 ++ ;
2024-12-22 00:02:33 +01:00
} else if ( outputPower >= 200 && outputPower < 300 ) {
2024-12-28 17:59:15 +01:00
output _more _than _200 ++ ;
2024-12-22 00:02:33 +01:00
} else if ( outputPower >= 300 ) {
2024-12-28 17:59:15 +01:00
feature . properties . puissance _haute = true ;
output _more _than _300 ++ ;
2024-12-22 00:02:33 +01:00
}
if ( feature . properties . tags [ 'charging_station:output' ] ) {
2024-12-28 17:59:15 +01:00
count _station _output ++ ;
2024-12-22 00:02:33 +01:00
}
if ( feature . properties . tags [ 'ref:EU:EVSE' ] ) {
2024-12-28 17:59:15 +01:00
count _ref _eu ++ ;
2024-12-22 00:02:33 +01:00
}
2024-12-28 17:59:15 +01:00
} ) ;
2024-12-22 00:02:33 +01:00
let bar _powers = ` <div class="bars-container">
2024-12-11 23:13:15 +01:00
< div class = "bar color-unknown" style = "width: ${calculerPourcentage(count_output_unknown, count, true)}%" > $ { count _output _unknown } < / d i v >
2024-12-22 19:07:09 +01:00
< div class = "bar color-power-lesser-than-50" style = "width: ${calculerPourcentage(count_station_outputoutput_between_1_and_50, count, true)}%" > $ { count _station _outputoutput _between _1 _and _50 ? count _station _outputoutput _between _1 _and _50 : '' } < / d i v >
< div class = "bar color-power-lesser-than-100" style = "width: ${calculerPourcentage(output_more_than_50, count, true)}%" > $ { output _more _than _50 ? output _more _than _50 : '' } < / d i v >
< div class = "bar color-power-lesser-than-200" style = "width: ${calculerPourcentage(output_more_than_100, count, true)}%" > $ { output _more _than _100 ? output _more _than _100 : '' } < / d i v >
2024-12-22 23:39:17 +01:00
< div class = "bar color-power-lesser-than-300" style = "width: ${calculerPourcentage(output_more_than_200, count, true)}%" > $ { output _more _than _200 ? output _more _than _200 : '' | '' } < / d i v >
2024-12-22 19:07:09 +01:00
< div class = "bar color-power-lesser-than-max" style = "width: ${calculerPourcentage(output_more_than_300, count, true)}%" > $ { output _more _than _300 ? output _more _than _300 : '' } < / d i v >
2024-12-28 17:59:15 +01:00
< / d i v > ` ;
2024-12-11 23:13:15 +01:00
2024-12-28 17:00:21 +01:00
let stats _content = ` <div class="stats-table">
2025-04-28 11:20:11 +02:00
< table style = "width: 100%;" >
2024-12-28 17:00:21 +01:00
< tr >
< th > Type < / t h >
< th > Nombre < / t h >
< th > Pourcentage < / t h >
< / t r >
< tr >
< td > Puissance inconnue < / t d >
< td > $ { count _output _unknown } < / t d >
< td > $ { calculerPourcentage ( count _output _unknown , count ) } % < / t d >
< / t r >
< tr >
< td > 1 - 50 kW < / t d >
< td > $ { count _station _outputoutput _between _1 _and _50 } < / t d >
< td > $ { calculerPourcentage ( count _station _outputoutput _between _1 _and _50 , count ) } % < / t d >
< / t r >
< tr >
< td > 50 - 100 kW < / t d >
< td > $ { output _more _than _50 } < / t d >
< td > $ { calculerPourcentage ( output _more _than _50 , count ) } % < / t d >
< / t r >
< tr >
< td > 100 - 200 kW < / t d >
< td > $ { output _more _than _100 } < / t d >
< td > $ { calculerPourcentage ( output _more _than _100 , count ) } % < / t d >
< / t r >
< tr >
< td > 200 - 300 kW < / t d >
< td > $ { output _more _than _200 } < / t d >
< td > $ { calculerPourcentage ( output _more _than _200 , count ) } % < / t d >
< / t r >
< tr >
< td > 300 + kW < / t d >
< td > $ { output _more _than _300 } < / t d >
< td > $ { calculerPourcentage ( output _more _than _300 , count ) } % < / t d >
< / t r >
< / t a b l e >
2024-12-28 17:59:15 +01:00
< / d i v > ` ;
2024-12-28 17:00:21 +01:00
2024-12-28 17:59:15 +01:00
$ ( '#found_charging_stations' ) . html ( stats _content ) ;
$ ( '#bars_power' ) . html ( bar _powers ) ;
2025-04-18 18:00:08 +02:00
// Remplacer la ligne existante par un appel à updateCounters
updateCounters ( ) ;
2025-04-20 00:54:04 +02:00
2025-04-18 18:00:08 +02:00
}
// Ajouter une fonction pour mettre à jour les compteurs
function updateCounters ( ) {
const stationsCount = geojsondata ? geojsondata . features . length : 0 ;
2025-04-28 13:23:12 +02:00
2025-04-28 10:08:31 +02:00
const osmoseText = lcm _config . osmoseIssuesList . length > 0 ? ` <span class="osmose-counter">(+ ${ lcm _config . osmoseIssuesList . length } ?)</span> ` : '' ;
2025-04-18 18:00:08 +02:00
$ ( '#count_features_fond' ) . html ( ` ⚡ ${ stationsCount } ${ osmoseText } stations ` ) ;
2024-12-11 23:13:15 +01:00
}
2024-12-11 17:32:48 +01:00
2025-04-18 16:50:26 +02:00
// Modifier bindEventsOnJosmRemote pour cibler les boutons dans un contexte (la popup)
function bindEventsOnJosmRemote ( popupElement ) {
// Cible tous les liens JOSM à l'intérieur de l'élément popup fourni
2025-04-28 16:17:13 +02:00
$ ( '#current_station_infos' ) . find ( '.edit-button.josm' ) . each ( function ( ) {
2025-04-18 16:50:26 +02:00
// Utiliser .off().on() pour éviter les liaisons multiples si la popup est rouverte
$ ( this ) . off ( 'click' ) . on ( 'click' , ( event ) => {
2025-04-20 00:32:45 +02:00
event . preventDefault ( ) ;
2025-04-18 16:50:26 +02:00
let josm _link = $ ( this ) . attr ( 'data-href' ) ;
console . log ( 'Sending command to JOSM:' , josm _link ) ;
2025-04-20 00:32:45 +02:00
2025-04-18 16:50:26 +02:00
fetch ( josm _link )
. then ( response => {
if ( ! response . ok ) {
// Gérer les erreurs de communication avec JOSM
console . error ( 'JOSM remote control error:' , response . status , response . statusText ) ;
alert ( 'Erreur de communication avec JOSM. Assurez-vous que JOSM est lancé et que le contrôle à distance est activé.' ) ;
} else {
console . log ( 'JOSM command sent successfully.' ) ;
// Optionnel: Afficher une notification de succès
}
} )
. catch ( error => {
console . error ( 'Failed to send command to JOSM:' , error ) ;
alert ( 'Impossible d\'envoyer la commande à JOSM. Est-il lancé et le contrôle à distance activé ?' ) ;
} ) ;
} ) ;
} ) ;
2024-12-12 00:27:27 +01:00
}
2024-12-14 18:00:09 +01:00
2024-12-31 23:27:19 +01:00
function displayPointsFromApi ( points , convert _to _osm _json ) {
if ( points && convert _to _osm _json ) {
2024-12-28 17:59:15 +01:00
geojsondata = osmtogeojson ( points ) ;
2024-12-23 00:02:46 +01:00
}
2024-12-22 00:02:33 +01:00
2025-04-20 00:54:04 +02:00
// Réinitialiser le compteur avant d'afficher les points
displayedStationsCount = 0 ;
2024-12-28 17:59:15 +01:00
displayStatsFromGeoJson ( geojsondata ) ;
2025-04-27 22:05:21 +02:00
let stats = {
count _hidden _by _filters : 0
} ;
displayStatsFromGeoJson ( geojsondata , stats ) ;
2024-12-22 00:02:33 +01:00
let resultLayer = L . geoJson ( geojsondata , {
style : function ( feature ) {
2025-04-18 16:50:26 +02:00
return { color : '#f00' } ;
2024-12-22 00:02:33 +01:00
} ,
filter : function ( feature , layer ) {
2024-12-28 17:59:15 +01:00
let isPolygon = ( feature . geometry ) && ( feature . geometry . type !== undefined ) && ( feature . geometry . type === 'Polygon' ) ;
2024-12-22 00:02:33 +01:00
if ( isPolygon ) {
2024-12-28 17:59:15 +01:00
feature . geometry . type = 'Point' ;
let polygonCenter = L . latLngBounds ( feature . geometry . coordinates [ 0 ] ) . getCenter ( ) ;
feature . geometry . coordinates = [ polygonCenter . lat , polygonCenter . lng ] ;
2024-12-22 00:02:33 +01:00
}
2024-12-28 17:59:15 +01:00
return true ;
2024-12-22 00:02:33 +01:00
} ,
onmoveend : function ( event ) {
2024-12-28 17:59:15 +01:00
// console.log('déplacement terminé');
2024-12-22 00:02:33 +01:00
} ,
onzoomend : function ( event ) {
2024-12-28 17:59:15 +01:00
supprimerMarqueurs ( ) ;
displayPointsFromApi ( ) ;
2024-12-22 00:02:33 +01:00
} ,
2024-12-22 23:39:17 +01:00
onEachFeature : eachFeature ,
2024-12-28 17:59:15 +01:00
} ) ;
2025-04-20 00:54:04 +02:00
// Mettre à jour le compteur de stations filtrées
updateFilteredStationsCount ( ) ;
2024-12-22 23:39:17 +01:00
}
2025-04-28 12:28:43 +02:00
function displaySocketsList ( feature ) {
2024-12-22 23:39:17 +01:00
2025-04-28 12:28:43 +02:00
let popupContent = '' ;
2024-12-22 23:39:17 +01:00
popupContent += '<div class="sockets-list" >'
let type2 = feature . properties . tags [ 'socket:type2' ]
let type2 _combo = feature . properties . tags [ 'socket:type2_combo' ]
if ( type2 ) {
popupContent += ' <img class="icon-img" src="img/Type2_socket.svg" alt="prise de type 2">'
if ( type2 !== 'yes' ) {
popupContent += '<span class="socket-counter">x ' + type2 + '</span>'
}
}
if ( feature . properties . tags [ 'socket:type2_combo' ] ) {
popupContent += ' <img class="icon-img" src="img/type2_combo.svg" alt="prise de type 2 combo CCS">'
if ( type2 _combo !== 'yes' ) {
popupContent += '<span class="socket-counter">x ' + type2 _combo + '</span>'
}
}
popupContent += '</div>'
2025-04-28 12:28:43 +02:00
return popupContent ;
}
function makePopupOfFeature ( feature ) {
let popupContent = ''
2024-12-22 23:39:17 +01:00
popupContent += '<div class="key-values" >'
// ne montrer que certains champs dans la popup
2024-12-31 22:56:45 +01:00
lcm _config . tags _to _display _in _popup . forEach ( function ( key ) {
if ( lcm _config . tags _to _display _in _popup . indexOf ( key ) ) {
2024-12-22 23:39:17 +01:00
let value = feature . properties . tags [ key ]
if ( value ) {
if ( value . indexOf ( 'http' ) !== - 1 ) {
value = '<a href="' + value + '">' + value + '</a>'
2024-12-22 00:02:33 +01:00
}
2024-12-22 23:39:17 +01:00
popupContent = popupContent + '<br/><strong class="popup-key">' + key + ' :</strong><span class="popup-value">' + value + '</span>'
2024-12-22 00:02:33 +01:00
}
2024-12-22 23:39:17 +01:00
}
} )
popupContent += '</div>'
return popupContent ;
}
2025-02-03 10:49:43 +01:00
/ * *
* application des filtres dans la sélection des bornes à afficher
* @ param feature
* @ param layer
* /
2025-04-27 22:05:21 +02:00
function eachFeature ( feature , layer , stats ) {
2025-04-20 00:32:45 +02:00
2025-04-28 12:36:46 +02:00
const maxPowerFilter = parseInt ( $ ( '#filter_max_output' ) . val ( ) ) || lcm _config . filter _max _output _default _value ;
let outPowerGuessed = lcm _utils . guessOutputPowerFromFeature ( feature ) ;
2025-04-20 00:32:45 +02:00
// Filtrage par puissance
if ( outPowerGuessed === 0 || outPowerGuessed === null ) {
if ( display _unknown _max _power _station === 'hide' ) {
return ;
}
} else {
// Filtrer les stations dont la puissance dépasse le maximum défini
if ( outPowerGuessed < maxPowerFilter ) {
return ;
}
}
2025-04-20 00:54:04 +02:00
// Incrémenter le compteur de stations affichées
displayedStationsCount ++ ;
2024-12-22 23:39:17 +01:00
2024-12-28 17:59:15 +01:00
let popupContent = makePopupOfFeature ( feature ) ;
layer . bindPopup ( popupContent ) ;
2024-12-22 23:39:17 +01:00
2025-04-27 21:47:38 +02:00
// Vérifier les filtres activés
if ( lcm _config . filterCCS && ! feature . properties . tags [ 'socket:type2_combo' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterType2 && ! feature . properties . tags [ 'socket:type2' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterDomestic && ! feature . properties . tags [ 'socket:typee' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterChademo && ! feature . properties . tags [ 'socket:chademo' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterType1 && ! feature . properties . tags [ 'socket:type1' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterType3 && ! feature . properties . tags [ 'socket:type3' ] ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
if ( lcm _config . filterCableAttached ) {
let hasCableAttached = false ;
// Vérifier si une des prises a un câble attaché
[ 'socket:type2:cable' , 'socket:type2_combo:cable' , 'socket:chademo:cable' , 'socket:typee:cable' , 'socket:type1:cable' , 'socket:type3:cable' ] . forEach ( tag => {
if ( feature . properties . tags [ tag ] === 'yes' ) {
hasCableAttached = true ;
}
} ) ;
if ( ! hasCableAttached ) {
2025-04-27 22:05:21 +02:00
stats . count _hidden _by _filters ++ ;
2025-04-27 21:47:38 +02:00
return ;
}
}
2025-04-28 12:36:46 +02:00
let displayOutPowerGuessed = '? kW' ;
2024-12-22 23:39:17 +01:00
if ( outPowerGuessed ) {
2024-12-28 17:59:15 +01:00
displayOutPowerGuessed = outPowerGuessed + ' kW max' ;
2025-02-03 13:41:48 +01:00
if ( display _unknown _max _power _station === 'show_only' ) {
2024-12-31 23:27:19 +01:00
return ;
}
2025-02-03 13:41:48 +01:00
} else {
2024-12-31 23:27:19 +01:00
// on cache cette station si on ne veut pas voir les stations à la puissance inconnue
2025-02-03 13:41:48 +01:00
if ( display _unknown _max _power _station === 'hide' ) {
2024-12-31 23:27:19 +01:00
return ;
}
2024-12-22 23:39:17 +01:00
}
2025-04-28 15:49:55 +02:00
2025-02-03 10:49:43 +01:00
/ * *
* bornes sans informations , suggérer d ' ajouter des tags dans OSM
* /
2024-12-22 23:39:17 +01:00
if ( ! popupContent ) {
popupContent = ` <span class="no-data"> Aucune information renseignée,
2024-12-28 17:59:15 +01:00
< a class = "edit-button" href = "https://www.openstreetmap.org/edit?editor=remote&node=${feature.properties.id}" > ajoutez la dans OpenStreetMap ! < / a > < / s p a n > ` ;
2024-12-22 23:39:17 +01:00
}
2024-12-14 18:00:09 +01:00
2024-12-31 23:27:19 +01:00
2025-05-01 12:28:43 +02:00
// Calcul du temps de recharge
let rechargeTimeText = '' ;
if ( outPowerGuessed && outPowerGuessed > 0 ) {
const hours = averageChargeKwh / outPowerGuessed ;
const minutes = Math . round ( hours * 60 ) ;
const h = Math . floor ( minutes / 60 ) ;
const m = minutes % 60 ;
rechargeTimeText = ` <div class="recharge-time">
2025-05-01 12:38:48 +02:00
⏱ ️ + $ { averageChargeKwh } kWh en < strong > $ { h > 0 ? h + 'h ' : '' } $ { m } min < / s t r o n g >
2025-05-01 12:28:43 +02:00
< / d i v > ` ;
}
2025-04-28 12:28:43 +02:00
// contenu de la popup
let html = ` <span class="color-indication" style="background-color: ${ lcm _color _utils . getColor ( feature ) } ;"> ${ displayOutPowerGuessed } </span>
2025-05-01 12:28:43 +02:00
$ { rechargeTimeText }
2025-04-28 15:49:55 +02:00
< div class = "popup-content" >
< div class = "socket-list" >
$ { displaySocketsList ( feature ) }
< / d i v >
< div class = "other-infos" >
2025-04-28 16:58:18 +02:00
<!-- $ { popupContent } -- >
2025-04-28 15:49:55 +02:00
< / d i v >
< / d i v >
2025-04-28 12:28:43 +02:00
`
2024-11-26 21:31:43 +01:00
2024-12-28 17:59:15 +01:00
let zoom = map . getZoom ( ) ;
let radius = 20 ;
let opacity = 0.5 ;
let ratio _circle = 10 ;
2024-12-22 23:39:17 +01:00
if ( zoom < 13 ) {
2024-12-28 17:59:15 +01:00
ratio _circle = 5 ;
2024-12-22 23:39:17 +01:00
} else if ( zoom < 15 ) {
2024-12-28 17:59:15 +01:00
ratio _circle = 1 ;
opacity = 0.25 ;
2024-12-22 23:39:17 +01:00
} else if ( zoom <= 16 ) {
2024-12-28 17:59:15 +01:00
ratio _circle = 0.5 ;
2024-12-22 23:39:17 +01:00
} else if ( zoom <= 18 ) {
2024-12-28 17:59:15 +01:00
ratio _circle = 0.25 ;
2024-12-22 23:39:17 +01:00
}
2024-12-28 17:59:15 +01:00
2024-12-23 00:26:13 +01:00
if ( ! layer . _latlng ) {
if ( lastLatLng ) {
2024-12-28 17:59:15 +01:00
layer . _latlng = lastLatLng ;
2024-12-23 00:26:13 +01:00
}
} else {
2024-12-28 17:59:15 +01:00
lastLatLng = layer . _latlng ;
2024-12-23 00:26:13 +01:00
}
2024-12-22 23:39:17 +01:00
if ( ! outPowerGuessed ) {
2024-12-28 17:59:15 +01:00
radius = radius * ratio _circle ;
2024-12-22 23:39:17 +01:00
} else {
2024-12-31 22:56:45 +01:00
/ * *
* limiter la taille du cercle pour les valeurs aberrantes
* les mettre en valeur en les plafonnant à 1 de plus que le maximum attendu en lcm _config
* /
2025-02-03 13:41:48 +01:00
if ( outPowerGuessed > lcm _config . max _possible _station _output ) {
console . error ( "valeur suspecte outPowerGuessed" , outPowerGuessed , feature )
outPowerGuessed = lcm _config . max _possible _station _output + 1
2024-12-31 22:44:33 +01:00
}
2024-12-28 17:59:15 +01:00
radius = outPowerGuessed * ratio _circle ;
2024-12-22 23:39:17 +01:00
}
2024-12-22 00:02:33 +01:00
2025-02-03 10:49:43 +01:00
/ * *
* gestion des marqueurs d ' alertes
* /
// info de câble manquant
2025-02-03 13:41:48 +01:00
if ( display _alert _cable _missing ) {
2025-02-03 10:49:43 +01:00
let keys = Object . keys ( feature . properties )
2025-02-03 11:18:34 +01:00
/ * *
* on considère l ' information de câble manquante uniquement dans le cas où une info de socket de type 2 est présente mais pas le tag socket : type2 _cable .
* /
2025-02-03 13:41:48 +01:00
if ( keys . indexOf ( 'socket:type2' ) !== - 1 && keys . indexOf ( 'socket:type2_cable' ) === - 1 ) {
2025-02-03 10:49:43 +01:00
let circle _alert = L . circle ( layer . _latlng , {
color : 'red' ,
fillColor : 'orange' ,
fillOpacity : 1 ,
colorOpacity : 0.5 ,
radius : 20
} )
circle _alert . bindPopup ( "information de câble manquante" ) ;
circle _alert . on ( {
mouseover : function ( ) {
this . openPopup ( ) ;
2025-04-18 16:50:26 +02:00
bindEventsOnJosmRemote ( this . getPopup ( ) . getElement ( ) ) ;
2025-02-03 10:49:43 +01:00
} ,
mouseout : function ( ) {
// setTimeout(() => this.closePopup(), 15000);
} ,
click : function ( ) {
this . openPopup ( ) ;
2025-04-18 16:50:26 +02:00
bindEventsOnJosmRemote ( this . getPopup ( ) . getElement ( ) ) ;
2025-02-03 11:18:34 +01:00
2025-02-03 10:49:43 +01:00
} ,
} ) ;
circle _alert . addTo ( all _stations _markers ) ;
}
}
/ * *
* affichage des marqueurs de stations de recharge
* /
2024-12-22 23:39:17 +01:00
let circle = L . circle ( layer . _latlng , {
2025-04-20 00:32:45 +02:00
color : lcm _color _utils . getColor ( feature ) ,
fillColor : lcm _color _utils . getColor ( feature ) ,
2024-12-22 23:39:17 +01:00
fillOpacity : opacity ,
colorOpacity : opacity ,
radius : radius
2024-12-28 17:59:15 +01:00
} ) . addTo ( all _stations _markers ) ;
2024-12-22 23:39:17 +01:00
if ( zoom > 15 ) {
let circle _center = L . circle ( layer . _latlng , {
color : 'black' ,
2025-04-20 00:32:45 +02:00
fillColor : lcm _color _utils . getColor ( feature ) ,
2024-12-22 23:39:17 +01:00
fillOpacity : 1 ,
radius : 0.1
2024-12-23 00:26:13 +01:00
} ) . addTo ( all _stations _markers ) ;
2024-12-22 23:39:17 +01:00
}
2024-12-22 00:02:33 +01:00
2025-04-28 15:49:55 +02:00
let badtags = lcm _utils . displayBadTagsFromFeature ( feature ) ;
if ( badtags !== valid _qa _message ) {
let circle _alert = L . circle ( layer . _latlng , {
color : 'red' ,
fillColor : 'orange' ,
fillOpacity : 0.5 ,
2025-04-28 16:17:13 +02:00
radius : radius * 0.85
2025-04-28 15:49:55 +02:00
} ) ;
circle _alert . bindTooltip ( badtags , {
2025-04-28 16:17:13 +02:00
// permanent: true,
2025-04-28 15:49:55 +02:00
direction : 'top'
} ) . addTo ( bad _tags _markers ) ;
}
2025-04-27 21:47:38 +02:00
circle . bindPopup ( html , {
autoPan : false ,
closeOnClick : false
} ) ;
2024-12-22 23:39:17 +01:00
circle . on ( {
mouseover : function ( ) {
2024-12-28 17:59:15 +01:00
this . openPopup ( ) ;
2025-04-28 16:17:13 +02:00
fillDetailsWithFeature ( feature ) ;
2025-04-18 16:50:26 +02:00
bindEventsOnJosmRemote ( this . getPopup ( ) . getElement ( ) ) ;
2024-12-22 23:39:17 +01:00
} ,
mouseout : function ( ) {
2024-12-28 17:59:15 +01:00
// setTimeout(() => this.closePopup(), 15000);
2024-12-22 23:39:17 +01:00
} ,
click : function ( ) {
2024-12-28 17:59:15 +01:00
this . openPopup ( ) ;
2025-04-28 12:28:43 +02:00
// Remplir automatiquement #current_station_infos lors du clic
2025-04-28 12:36:46 +02:00
fillDetailsWithFeature ( feature ) ;
2025-04-28 16:17:13 +02:00
bindEventsOnJosmRemote ( this . getPopup ( ) . getElement ( ) ) ;
2025-04-28 12:36:46 +02:00
} ,
} ) ;
2025-04-28 12:28:43 +02:00
2025-04-28 15:49:55 +02:00
2025-04-28 12:36:46 +02:00
}
/ * *
* Remplit le contenu de # current _station _infos avec les informations de la station
* @ param { * } feature
* /
function fillDetailsWithFeature ( feature ) {
2025-05-01 12:28:43 +02:00
// Stocker le feature courant pour pouvoir rafraîchir le détail si besoin
$ ( '#current_station_infos' ) . data ( 'currentFeature' , feature ) ;
2025-04-28 12:36:46 +02:00
// Ajout du lien vers Panoramax
const panoramaxLink = ` https://api.panoramax.xyz/#focus=map&map=16.7/ ${ feature . geometry . coordinates [ 1 ] } / ${ feature . geometry . coordinates [ 0 ] } &speed=250 ` ;
2025-04-28 12:28:43 +02:00
2025-04-28 12:36:46 +02:00
let link _josm = createJOSMEditLink ( feature ) ;
let outPowerGuessed = lcm _utils . guessOutputPowerFromFeature ( feature ) ;
let displayOutPowerGuessed = '? kW' ;
if ( outPowerGuessed ) {
displayOutPowerGuessed = outPowerGuessed + ' kW max' ;
}
2025-05-01 12:28:43 +02:00
// AJOUT : Calcul du temps de recharge pour le panneau latéral
let rechargeTimeText = '' ;
if ( outPowerGuessed && outPowerGuessed > 0 ) {
const hours = averageChargeKwh / outPowerGuessed ;
const minutes = Math . round ( hours * 60 ) ;
const h = Math . floor ( minutes / 60 ) ;
const m = minutes % 60 ;
rechargeTimeText = ` <div class="recharge-time">
2025-05-01 12:38:48 +02:00
⏱ ️ < strong > $ { h > 0 ? h + 'h ' : '' } $ { m } min < / s t r o n g > p o u r $ { a v e r a g e C h a r g e K w h } k W h à $ { o u t P o w e r G u e s s e d } k W :
2025-05-01 12:28:43 +02:00
< / d i v > ` ;
} else {
rechargeTimeText = ` <div class="recharge-time">⏱️ Temps estimé : puissance inconnue</div> ` ;
}
2025-04-28 12:36:46 +02:00
let content = '' ;
let table _details = '' ;
let count _features _in _table = 0 ;
table _details += '<div class="key-values" >'
// ne montrer que certains champs dans la popup
2025-04-28 12:45:58 +02:00
lcm _config . tags _to _display _in _popup . forEach ( ( key ) => {
2025-04-28 12:36:46 +02:00
if ( lcm _config . tags _to _display _in _popup . indexOf ( key ) ) {
let value = feature . properties . tags [ key ]
if ( value ) {
if ( value . indexOf ( 'http' ) !== - 1 ) {
value = '<a href="' + value + '">' + value + '</a>'
}
table _details += '<br/><strong class="popup-key">' + key + ' :</strong><span class="popup-value">' + value + '</span>'
count _features _in _table ++ ;
2025-04-28 12:28:43 +02:00
}
2025-04-28 12:36:46 +02:00
}
} )
table _details += '</div>'
if ( ! count _features _in _table ) {
table _details += '<div class="no-feature-in-table">Aucune information renseignée</div>'
}
2025-05-01 12:50:37 +02:00
// panel de détails dans le volet latéral
2025-05-01 12:28:43 +02:00
content += `
2025-05-01 12:50:37 +02:00
2025-05-01 12:28:43 +02:00
< span class = "color-indication" style = "background-color: ${lcm_color_utils.getColor(feature)};" > $ { displayOutPowerGuessed } < / s p a n >
2025-05-01 12:50:37 +02:00
< div class = "buttons-land " >
2025-05-01 12:28:43 +02:00
< a href = "https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_car#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class = "navigation-link by-car" title = "itinéraire en voiture vers cette station" > 🚗 < / a >
< a href = "https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_bike#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class = "navigation-link by-car" title = "itinéraire en vélo vers cette station" > 🚴 ♀ ️ < / a >
< a href = "https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_foot#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class = "navigation-link by-car" title = "itinéraire à pied vers cette station" > 👠 < / a >
< a class = "edit-button" href = "https://www.openstreetmap.org/edit?editor=id&node=${feature.properties.id}" > ✏ ️ < / a >
< a class = "edit-button josm" data - href = "${link_josm}" href = "#" > JOSM < / a >
< a href = "${makeMapCompleteUrl(feature)}" target = "_blank" class = "edit-button mapcomplete-link" title = "Voir sur MapComplete" >
< img src = "https://mapcomplete.org/assets/themes/charging_stations/plug.svg" alt = "icone" >
< / a >
< a href = "${panoramaxLink}" target = "_blank" class = "panoramax-link" title = "Voir sur Panoramax" >
< img src = "styles/images/panoramax.ico" alt = "icone" >
< / a >
2025-05-01 12:50:37 +02:00
< / d i v >
$ { rechargeTimeText }
2025-05-01 12:28:43 +02:00
< div class = "socket-list" >
$ { displaySocketsList ( feature ) }
< / d i v >
< div class = "table-details" >
$ { table _details }
< / d i v >
< div class = "bad-tags" >
< h3 > Problèmes de qualité < / h 3 >
$ { lcm _utils . displayBadTagsFromFeature ( feature ) }
< / d i v >
`
2025-04-28 12:36:46 +02:00
$ ( '#current_station_infos' ) . html ( ` <div class='island irve-details'><h2>Détails</h2> ${ content } </div> ` ) ;
2024-10-17 15:01:47 +02:00
}
2025-04-28 13:23:12 +02:00
function makeMapCompleteUrl ( feature ) {
// https://mapcomplete.org/charging_stations.html?z=16.3&lat=48.85770772656571&lon=2.353630884174322#node/123454656
const center = map . getCenter ( )
const zoom = map . getZoom ( )
return ` https://mapcomplete.org/charging_stations.html?z= ${ zoom } &lat= ${ center . lat } &lon= ${ center . lng } #node/ ${ feature . properties . id } `
}
2025-02-03 13:41:48 +01:00
function bindFullDetails ( feature ) {
$ ( '#fullDetails' ) . on ( 'click' , ( ) => {
2025-04-28 12:28:43 +02:00
2025-02-03 13:41:48 +01:00
$ ( '#current_station_infos' ) [ 0 ] . innerHTML = ` <h2>Détails</h2>
2025-04-28 12:28:43 +02:00
$ { makePopupOfFeature ( feature ) }
`
2025-02-03 13:41:48 +01:00
} )
2025-02-03 11:18:34 +01:00
}
2024-10-17 15:01:47 +02:00
let isLoading = false
2024-12-22 00:02:33 +01:00
function loadOverpassQuery ( ) {
if ( ! isLoading ) {
2024-12-28 17:59:15 +01:00
isLoading = true ;
$ ( '#spinning_icon' ) . fadeIn ( ) ;
let queryTextfieldValue = $ ( '#query-textfield' ) . val ( ) ;
let overpassApiUrl = buildOverpassApiUrl ( map , queryTextfieldValue ) ;
2024-12-22 00:02:33 +01:00
$ . get ( overpassApiUrl , function ( geoDataPointsFromApi ) {
2024-12-28 17:59:15 +01:00
geojsondata = geoDataPointsFromApi ;
2024-12-31 23:27:19 +01:00
refreshDisplay ( true ) ;
2024-12-28 17:59:15 +01:00
$ ( '#spinning_icon' ) . fadeOut ( ) ;
$ ( '#message-loading' ) . fadeOut ( ) ;
isLoading = false ;
} ) ;
2024-12-22 00:02:33 +01:00
}
2024-10-17 15:01:47 +02:00
}
2025-02-03 13:41:48 +01:00
function refreshDisplay ( convert _points _to _osm = false ) {
2024-12-28 17:59:15 +01:00
supprimerMarqueurs ( ) ;
2025-04-27 21:47:38 +02:00
count _hidden _by _filters = 0 ; // Réinitialiser le compteur
2025-04-20 00:32:45 +02:00
if ( geojsondata ) {
displayPointsFromApi ( geojsondata , convert _points _to _osm ) ;
2025-04-20 00:54:04 +02:00
updateCounters ( ) ;
updateFilteredStationsCount ( ) ;
2025-04-20 00:32:45 +02:00
}
2025-04-27 22:24:09 +02:00
2025-04-27 21:47:38 +02:00
// Mettre à jour le compteur dans la popup
let count = geojsondata . features . length ;
let disabledFilters = 0 ;
Object . keys ( lcm _config . filterConfigs ) . forEach ( filterId => {
if ( ! lcm _config . filterConfigs [ filterId ] ) disabledFilters ++ ;
} ) ;
$ ( '#count_features_fond' ) . html ( '⚡' + count + ' stations' + ( disabledFilters > 0 ? ` ( ${ disabledFilters } filtre ${ disabledFilters > 1 ? 's' : '' } désactivé ${ disabledFilters > 1 ? 's' : '' } , ${ count _hidden _by _filters } masqué ${ count _hidden _by _filters > 1 ? 's' : '' } ) ` : '' ) ) ;
2024-12-22 23:39:17 +01:00
}
2024-12-22 00:02:33 +01:00
function onMapMoveEnd ( ) {
let center = map . getCenter ( )
let zoom = map . getZoom ( )
let infos = ` Lat: ${ center . lat } , Lon: ${ center . lng } , Zoom : ${ zoom } `
2024-12-28 23:14:38 +01:00
2025-04-28 12:28:43 +02:00
updateURLWithMapCoordinatesAndZoom ( ) ;
2024-12-28 13:29:29 +01:00
if ( zoom < 10 ) {
$ ( '#zoomMessage' ) . show ( )
2024-12-22 00:02:33 +01:00
} else {
2024-12-28 13:29:29 +01:00
$ ( '#zoomMessage' ) . hide ( )
loadOverpassQuery ( )
2024-12-22 00:02:33 +01:00
}
2024-12-28 23:14:38 +01:00
if ( map . getZoom ( ) > 14 ) {
searchFoodPlaces ( map ) ;
} else {
food _places _markers . clearLayers ( ) ;
}
2024-12-22 00:02:33 +01:00
$ ( '#infos_carte' ) . html ( infos )
2024-12-28 17:00:21 +01:00
// Stocker les dernières coordonnées connues
if ( ! window . lastKnownPosition ) {
window . lastKnownPosition = center ;
2025-02-03 10:49:43 +01:00
2024-12-28 17:00:21 +01:00
} else {
// Calculer la distance en km entre l'ancienne et la nouvelle position
const distanceKm = map . distance ( center , window . lastKnownPosition ) / 1000 ;
2025-02-03 13:41:48 +01:00
2025-04-18 17:53:07 +02:00
console . log ( 'déplacement de ' , distanceKm , 'km' )
2024-12-28 17:00:21 +01:00
// Ne mettre à jour que si on s'est déplacé de plus de 2km
if ( distanceKm > 2 ) {
window . lastKnownPosition = center ;
updateURLWithMapCoordinatesAndZoom ( ) ;
}
}
2024-12-16 12:54:15 +01:00
2025-04-18 16:50:26 +02:00
// Ajout d'un log pour déboguer
console . log ( "Zoom actuel:" , map . getZoom ( ) ) ;
2025-04-18 17:53:07 +02:00
if ( map . getZoom ( ) >= 12 ) {
2025-04-20 00:32:45 +02:00
// console.log("Recherche des issues Osmose...");
2025-04-18 16:50:26 +02:00
searchOsmoseIssues ( map ) ;
} else {
console . log ( "Zoom trop faible pour les issues Osmose" ) ;
osmose _markers . clearLayers ( ) ;
}
2024-12-12 00:27:27 +01:00
}
2024-12-16 12:54:15 +01:00
setCoordinatesOfLeafletMapFromQueryParameters ( )
2025-05-01 12:28:43 +02:00
import { lcm _i18n } from './lcm_i18n.js' ;
2024-12-14 18:00:09 +01:00
$ ( document ) . ready ( function ( ) {
2025-05-01 12:28:43 +02:00
// Charger le service de traduction
// Détecter la langue du navigateur
const currentLanguage = lcm _i18n . detectLanguage ( ) ;
console . log ( 'Langue détectée:' , currentLanguage ) ;
2025-04-27 21:47:38 +02:00
init ( )
2024-12-28 17:59:15 +01:00
} ) ;
2024-12-16 12:13:19 +01:00
2024-12-22 00:02:33 +01:00
function showActiveFilter ( filterVariableName , selectorId ) {
2024-12-22 23:39:17 +01:00
$ ( selectorId ) . attr ( 'class' , 'filter-state-' + filterVariableName )
2024-12-22 00:02:33 +01:00
}
2025-02-03 10:49:43 +01:00
/ * *
* mettre à jour les liens vers des éditeurs externes
* /
2025-02-03 13:41:48 +01:00
function updateExternalEditorsLinks ( ) {
2025-02-03 10:49:43 +01:00
const center = map . getCenter ( )
const zoom = map . getZoom ( )
2025-02-03 13:41:48 +01:00
mapCompleteLink ( center . lat , center . lng , zoom )
idLink ( center . lat , center . lng , zoom )
2025-02-03 10:49:43 +01:00
}
2025-02-03 13:41:48 +01:00
function mapCompleteLink ( lat , lon , zoom ) {
$ ( "mapCompleteLink" ) . attr ( 'href' , ` https://mapcomplete.org/charging_stations?z= ${ zoom } &lat= ${ lat } &lon= ${ lon } ` )
2025-02-03 10:49:43 +01:00
}
2025-02-03 13:41:48 +01:00
function idLink ( lat , lon , zoom ) {
let href = ` https://www.openstreetmap.org/edit?editor=id#map= ${ zoom } / ${ lat } / ${ lon } `
2025-02-03 10:49:43 +01:00
console . log ( 'idlink' , href )
$ ( "idLink" ) . attr ( 'href' , href )
}
2024-12-28 17:00:21 +01:00
2024-12-22 00:02:33 +01:00
function cycleVariableState ( filterVariableName , selectorId ) {
2024-12-22 23:39:17 +01:00
console . log ( 'filterVariableName' , filterVariableName , filterStatesAvailable )
2024-12-22 00:02:33 +01:00
if ( filterVariableName ) {
if ( filterVariableName == filterStatesAvailable [ 0 ] ) {
filterVariableName = filterStatesAvailable [ 1 ]
} else if ( filterVariableName == filterStatesAvailable [ 1 ] ) {
filterVariableName = filterStatesAvailable [ 2 ]
} else if ( filterVariableName == filterStatesAvailable [ 2 ] ) {
filterVariableName = filterStatesAvailable [ 0 ]
}
} else {
filterVariableName = filterStatesAvailable [ 0 ]
}
showActiveFilter ( filterVariableName , selectorId )
2024-12-22 23:39:17 +01:00
console . log ( 'filterVariableName after' , filterVariableName )
2024-12-22 00:02:33 +01:00
return filterVariableName
}
2024-12-16 12:13:19 +01:00
2024-12-28 13:29:29 +01:00
// toggle des stats
2025-02-03 13:41:48 +01:00
$ ( '#toggle-stats' ) . on ( 'click' , function ( ) {
2024-12-28 13:29:29 +01:00
$ ( '#found_charging_stations' ) . slideToggle ( ) ;
2025-02-03 13:41:48 +01:00
2024-12-28 13:29:29 +01:00
// Change le symbole de la flèche
let text = $ ( this ) . text ( ) ;
2025-02-03 13:41:48 +01:00
if ( text . includes ( '🔽' ) ) {
2024-12-28 13:29:29 +01:00
$ ( this ) . text ( text . replace ( '🔽' , '🔼' ) ) ;
} else {
2025-02-03 13:41:48 +01:00
$ ( this ) . text ( text . replace ( '🔼' , '🔽' ) ) ;
2024-12-28 13:29:29 +01:00
}
} ) ;
2024-12-28 17:00:21 +01:00
2025-04-20 00:32:45 +02:00
2024-12-28 17:00:21 +01:00
// Ajouter ces variables avec les autres déclarations globales
let food _places _markers = L . layerGroup ( ) ;
const foodIcon = L . divIcon ( {
className : 'food-marker' ,
html : '🍽️' ,
iconSize : [ 20 , 20 ] ,
iconAnchor : [ 10 , 10 ]
} ) ;
// Ajouter cette fonction avec les autres fonctions de recherche
function searchFoodPlaces ( map ) {
const bounds = map . getBounds ( ) ;
const bbox = bounds . getSouth ( ) + ',' + bounds . getWest ( ) + ',' + bounds . getNorth ( ) + ',' + bounds . getEast ( ) ;
2025-02-03 13:41:48 +01:00
2024-12-28 17:00:21 +01:00
const query = `
[ out : json ] [ timeout : 25 ] ;
(
2025-04-18 16:50:26 +02:00
nwr [ "amenity" = "restaurant" ] ( $ { bbox } ) ;
nwr [ "amenity" = "cafe" ] ( $ { bbox } ) ;
2024-12-28 17:00:21 +01:00
) ;
2025-04-18 16:50:26 +02:00
out center ; ` ;
2024-12-28 17:00:21 +01:00
const url = ` https://overpass-api.de/api/interpreter?data= ${ encodeURIComponent ( query ) } ` ;
food _places _markers . clearLayers ( ) ;
fetch ( url )
. then ( response => response . json ( ) )
. then ( data => {
2025-04-18 16:50:26 +02:00
data . elements . forEach ( element => {
// Utiliser les coordonnées du centre pour les ways et relations
const lat = element . lat || element . center . lat ;
const lon = element . lon || element . center . lon ;
const name = element . tags . name || 'Sans nom' ;
const type = element . tags . amenity ;
const marker = L . marker ( [ lat , lon ] , {
2024-12-28 17:00:21 +01:00
icon : foodIcon
} ) ;
2025-02-03 13:41:48 +01:00
2024-12-28 17:00:21 +01:00
marker . bindPopup ( `
< strong > $ { name } < / s t r o n g > < b r >
Type : $ { type } < br >
2025-04-18 16:50:26 +02:00
$ { element . tags . cuisine ? 'Cuisine: ' + element . tags . cuisine : '' }
2024-12-28 17:00:21 +01:00
` );
2025-02-03 13:41:48 +01:00
2024-12-28 17:00:21 +01:00
food _places _markers . addLayer ( marker ) ;
} ) ;
} )
. catch ( error => console . error ( 'Erreur lors de la recherche des restaurants:' , error ) ) ;
}
2025-04-18 16:50:26 +02:00
// Ajouter après la déclaration des autres variables globales
let osmose _markers = L . layerGroup ( ) ;
const osmoseIcon = L . divIcon ( {
className : 'osmose-marker-drop' ,
html : '<div class="osmose-marker-inner">⚡</div>' ,
iconSize : [ 30 , 40 ] ,
iconAnchor : [ 15 , 40 ]
} ) ;
2025-04-18 17:53:07 +02:00
// Ajouter cette fonction utilitaire pour calculer la distance entre deux points
function calculateDistance ( lat1 , lon1 , lat2 , lon2 ) {
return L . latLng ( lat1 , lon1 ) . distanceTo ( [ lat2 , lon2 ] ) ;
}
// Ajouter cette fonction pour vérifier si le calque des stations est actif
function isChargingStationLayerActive ( ) {
return map . hasLayer ( all _stations _markers ) ;
}
// Modifier la fonction searchOsmoseIssues
2025-04-18 16:50:26 +02:00
function searchOsmoseIssues ( map ) {
const bounds = map . getBounds ( ) ;
const zoom = map . getZoom ( ) ;
const bbox = ` ${ bounds . getWest ( ) } %2C ${ bounds . getSouth ( ) } %2C ${ bounds . getEast ( ) } %2C ${ bounds . getNorth ( ) } ` ;
const url = ` https://osmose.openstreetmap.fr/api/0.3/issues?zoom= ${ zoom } &item=8410%2C8411&level=1%2C2%2C3&limit=500&bbox= ${ bbox } ` ;
osmose _markers . clearLayers ( ) ;
2025-04-18 17:53:07 +02:00
// Modifier la vérification des stations existantes
const existingStations = [ ] ;
if ( lcm _config . hide _osmose _markers _if _close _to _existing _charging _stations &&
isChargingStationLayerActive ( ) && // Nouvelle condition
geojsondata &&
geojsondata . features ) {
geojsondata . features . forEach ( feature => {
if ( feature . geometry && feature . geometry . coordinates ) {
existingStations . push ( {
lat : feature . geometry . coordinates [ 1 ] ,
lon : feature . geometry . coordinates [ 0 ]
} ) ;
}
} ) ;
}
2025-04-18 16:50:26 +02:00
fetch ( url )
. then ( response => {
if ( ! response . ok ) {
return response . text ( ) . then ( text => { throw new Error ( ` Erreur HTTP ${ response . status } : ${ response . statusText } . Réponse : ${ text } ` ) ; } ) ;
}
return response . json ( ) ;
} )
. then ( data => {
if ( ! data || ! Array . isArray ( data . issues ) ) {
console . warn ( "Réponse Osmose (liste) inattendue ou pas d'issues:" , data ) ;
2025-04-18 18:00:08 +02:00
osmoseIssuesCount = 0 ;
updateCounters ( ) ;
2025-04-18 16:50:26 +02:00
return ;
}
const issuesList = data . issues ;
2025-04-28 10:08:31 +02:00
lcm _config . osmoseIssuesList = [ ] ;
2025-04-18 18:00:08 +02:00
osmoseIssuesCount = issuesList . length ;
2025-04-18 16:50:26 +02:00
issuesList . forEach ( issueInfo => {
2025-04-18 17:53:07 +02:00
if ( issueInfo . lat == null || issueInfo . lon == null || ! issueInfo . id ) {
return ;
2025-04-18 16:50:26 +02:00
}
const lat = parseFloat ( issueInfo . lat ) ;
const lon = parseFloat ( issueInfo . lon ) ;
2025-04-18 17:53:07 +02:00
// Vérifier la distance avec les stations existantes
if ( lcm _config . hide _osmose _markers _if _close _to _existing _charging _stations ) {
const tooClose = existingStations . some ( station => {
const distance = calculateDistance ( lat , lon , station . lat , station . lon ) ;
return distance <= lcm _config . hide _osmose _markers _if _close _to _existing _charging _stations _distance ;
} ) ;
if ( tooClose ) {
2025-04-18 23:36:04 +02:00
// console.log(`Marqueur Osmose ignoré car trop proche d'une station existante: ${lat},${lon}`);
2025-04-18 17:53:07 +02:00
return ;
}
2025-04-18 16:50:26 +02:00
}
2025-04-28 10:08:31 +02:00
lcm _config . osmoseIssuesList . push ( issueInfo ) ;
2025-04-18 17:53:07 +02:00
// Créer le marqueur Osmose si il n'est pas trop proche d'une station existante
2025-04-18 16:50:26 +02:00
const osmoseMarker = L . circle ( [ lat , lon ] , {
color : "purple" ,
fillColor : "purple" ,
fillOpacity : 0.8 ,
radius : 10 ,
className : 'leaflet-osmose-layer' ,
pane : 'markerPane' ,
2025-04-18 17:53:07 +02:00
issueId : issueInfo . id
2025-04-18 16:50:26 +02:00
} ) ;
// Préparer une popup de chargement simple
osmoseMarker . bindPopup ( "Chargement des détails..." ) ;
osmoseMarker . on ( 'click' , function ( e ) {
const clickedMarker = e . target ;
const storedIssueId = clickedMarker . options . issueId ;
const detailUrl = ` https://osmose.openstreetmap.fr/api/0.3/issue/ ${ storedIssueId } ?langs=auto ` ;
console . log ( "Récupération des détails pour l'issue:" , detailUrl ) ;
fetch ( detailUrl )
. then ( response => {
if ( ! response . ok ) {
return response . text ( ) . then ( text => { throw new Error ( ` Erreur HTTP ${ response . status } : ${ response . statusText } . Réponse : ${ text } ` ) ; } ) ;
}
return response . json ( ) ;
} )
. then ( issueDetails => {
// Construire le contenu de la popup avec les détails
let popupContent = ` <strong> ${ issueDetails . title ? . auto || 'Titre non disponible' } </strong><br> ` ;
if ( issueDetails . subtitle ? . auto ) {
popupContent += ` <p> ${ issueDetails . subtitle . auto } </p> ` ;
}
let proposedTags = '' ;
if ( issueDetails . new _elems && issueDetails . new _elems [ 0 ] && issueDetails . new _elems [ 0 ] . add ) {
proposedTags = '<table class="proposed-tags">' ;
issueDetails . new _elems [ 0 ] . add . forEach ( tag => {
proposedTags += ` <tr><td> ${ tag . k } </td><td> ${ tag . v } </td></tr> ` ;
} ) ;
proposedTags += '</table>' ;
2025-04-28 12:28:43 +02:00
// popupContent += `<div class="proposed-tags-container"><h4>Tags proposés :</h4>${proposedTags}</div>`;
2025-04-18 16:50:26 +02:00
}
// Construire le lien JOSM /import
const josmFixUrl = ` http://localhost:8111/import?url=https://osmose.openstreetmap.fr/api/0.3/issue/ ${ storedIssueId } /fix/0 ` ;
2025-04-28 12:28:43 +02:00
let josm _buttons = `
2025-04-18 16:50:26 +02:00
< div class = "action-buttons" >
< a class = "edit-button josm" data - href = "${josmFixUrl}" href = "#" title = "Ouvre JOSM et charge la correction proposée" > ⚡ Réparer dans JOSM < / a >
< a href = "https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target = "_blank" title = "Voir les détails de l'alerte sur le site Osmose" > Voir sur Osmose < / a >
< / d i v > ` ;
2025-04-28 12:28:43 +02:00
popupContent += josm _buttons
2025-04-18 16:50:26 +02:00
// Mettre à jour le contenu de la popup et s'assurer qu'elle est ouverte
clickedMarker . setPopupContent ( popupContent ) ;
2025-04-28 11:20:11 +02:00
// clickedMarker.openPopup(); // Rouvrir pour ajuster la taille si nécessaire
2025-04-18 16:50:26 +02:00
2025-04-28 12:28:43 +02:00
$ ( '#current_station_infos' ) . html ( ` <div class='island osmose-details'><h2>Analyse Osmose</h2> ${ josm _buttons }
$ { proposedTags }
< / d i v > ` ) ;
2025-04-18 16:50:26 +02:00
// Lier l'événement au bouton JOSM DANS la popup
bindEventsOnJosmRemote ( clickedMarker . getPopup ( ) . getElement ( ) ) ;
} )
. catch ( error => {
console . error ( "Erreur lors de la récupération des détails de l'issue Osmose:" , error ) ;
clickedMarker . setPopupContent ( ` Erreur lors du chargement des détails.<br><a href="https://osmose.openstreetmap.fr/fr/issue/ ${ storedIssueId } " target="_blank">Voir sur Osmose</a> ` ) ;
2025-04-28 11:20:11 +02:00
// clickedMarker.openPopup();
2025-04-18 16:50:26 +02:00
} ) ;
} ) ;
osmose _markers . addLayer ( osmoseMarker ) ;
} ) ;
2025-04-18 18:00:08 +02:00
updateCounters ( ) ; // Mettre à jour l'affichage après le traitement
2025-04-18 16:50:26 +02:00
} )
. catch ( error => {
console . error ( 'Erreur détaillée lors de la recherche de la liste des issues Osmose:' , error ) ;
2025-04-18 18:00:08 +02:00
osmoseIssuesCount = 0 ;
updateCounters ( ) ;
2025-04-18 16:50:26 +02:00
} ) ;
}
2024-12-28 17:00:21 +01:00
2025-04-18 17:53:07 +02:00
// Ajouter un écouteur d'événements pour le changement de visibilité des calques
function init ( ) {
2025-04-28 11:20:11 +02:00
bindEventsOnJosmRemote ( ) ;
onMapMoveEnd ( ) ;
map . on ( 'moveend' , onMapMoveEnd ) ;
$ ( '#spinning_icon' ) . hide ( ) ;
2025-04-27 21:47:38 +02:00
2025-04-28 11:20:11 +02:00
/ * *
* boutons de changement de filtres et de rechargement des bornes à l ' affichage
* /
$ ( '#removeMarkers' ) . on ( 'click' , function ( ) {
supprimerMarqueurs ( ) ;
} ) ;
$ ( '#load' ) . on ( 'click' , function ( ) {
loadOverpassQuery ( ) ;
} ) ;
$ ( '#toggleSidePanel' ) . on ( 'click' , function ( ) {
console . log ( 'toggleSidePanel' , $ ( this ) )
$ ( 'body' ) . toggleClass ( 'side-panel-open' ) ;
} ) ;
$ ( '#chercherButton' ) . on ( 'click' , function ( ) {
supprimerMarqueurs ( ) ;
loadOverpassQuery ( ) ;
2025-04-28 13:23:12 +02:00
geoDataPointsFromApi ( ) ;
2025-04-28 11:20:11 +02:00
} ) ;
$ ( '#setRandomView' ) . on ( 'click' , function ( ) {
setRandomView ( ) ;
loadOverpassQuery ( ) ;
2025-04-28 12:28:43 +02:00
geoDataPointsFromApi ( ) ;
2025-04-28 11:20:11 +02:00
} ) ;
$ ( '#filterUnkown' ) . on ( 'click' , function ( ) {
display _unknown _max _power _station = cycleVariableState ( display _unknown _max _power _station , '#filterUnkown' ) ;
2025-04-27 21:47:38 +02:00
showActiveFilter ( display _unknown _max _power _station , '#filterUnkown' ) ;
2025-04-28 11:20:11 +02:00
refreshDisplay ( ) ;
} ) ;
/ * *
* toggle des alertes de tags décrivant la présence de cable
* /
$ ( '#cableMissing' ) . on ( 'click' , function ( ) {
display _alert _cable _missing = ! display _alert _cable _missing ;
showActiveFilter ( display _alert _cable _missing , '#cableMissing' ) ;
refreshDisplay ( ) ;
} ) ;
showActiveFilter ( display _unknown _max _power _station , '#filterUnkown' ) ;
2025-04-27 21:47:38 +02:00
2025-04-28 11:20:11 +02:00
$ ( '#shareUrl' ) . on ( 'click' , copyCurrentUrl ) ;
2025-04-27 21:47:38 +02:00
2025-04-28 11:20:11 +02:00
// Initialisation des états des checkboxes des filtres selon les valeurs de configuration
Object . keys ( lcm _config . filterConfigs ) . forEach ( filterId => {
2025-04-28 13:23:12 +02:00
2025-04-28 11:20:11 +02:00
$ ( ` # ${ filterId } ` ) . prop ( 'checked' , lcm _config . filterConfigs [ filterId ] ) ;
} ) ;
// Écouteurs pour les filtres
Object . keys ( lcm _config . filterConfigs ) . forEach ( filterId => {
$ ( ` # ${ filterId } ` ) . on ( 'change' , function ( ) {
lcm _config [ lcm _config . filterConfigs [ filterId ] ] = this . checked ;
refreshDisplay ( ) ;
2025-04-27 22:24:09 +02:00
} ) ;
2025-04-28 11:20:11 +02:00
} ) ;
2025-04-28 15:49:55 +02:00
$ ( '#filterBadTags' ) . on ( 'click' , function ( ) {
lcm _config . display _alert _bad _tags = ! lcm _config . display _alert _bad _tags ;
showActiveFilter ( lcm _config . display _alert _bad _tags , '#filterBadTags' ) ;
if ( lcm _config . display _alert _bad _tags ) {
bad _tags _markers . clearLayers ( ) ;
bad _tags _markers . addTo ( map ) ;
} else {
bad _tags _markers . remove ( ) ;
}
refreshDisplay ( ) ;
} ) ;
2024-12-28 17:59:15 +01:00
2025-04-18 16:50:26 +02:00
2025-04-28 15:49:55 +02:00
if ( lcm _config . display _restaurants _and _cafes ) {
food _places _markers . addTo ( map ) ;
}
2025-04-20 00:32:45 +02:00
2025-04-28 11:20:11 +02:00
// Mettre à jour le contrôle des calques
const overlayMaps = {
// ...baseLayers,
// "🗺️ Fond de carte": baseLayers,
"⚡ Stations de recharge" : all _stations _markers ,
"☕ Restaurants et cafés" : food _places _markers ,
2025-04-28 15:49:55 +02:00
"💡 Bornes potentielles (Osmose)" : osmose _markers ,
"💡 Problèmes de qualité" : bad _tags _markers
2025-04-28 11:20:11 +02:00
} ;
2025-04-20 00:32:45 +02:00
2025-04-28 11:20:11 +02:00
const overlayControl = L . control . layers ( baseLayers , overlayMaps , {
// collapsed: false,
className : 'leaflet-control-layers overlay-layers' ,
id : 'overlay-layers-control'
} )
. addTo ( map ) ;
2025-04-18 16:50:26 +02:00
2025-04-28 11:20:11 +02:00
$ ( '#sendToJOSM' ) . on ( 'click' , ( ) => {
sendToJOSM ( map , geojsondata )
. then ( ( ) => {
console . log ( 'Données envoyées à JOSM avec succès !' ) ;
} )
. catch ( ( ) => {
alert ( 'Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée' ) ;
} ) ;
} ) ;
$ ( '#josmLink' ) . on ( 'click' , ( ) => {
sendToJOSM ( map , geojsondata )
. then ( ( ) => {
console . log ( 'Données envoyées à JOSM avec succès !' ) ;
} )
. catch ( ( ) => {
alert ( 'Erreur : JOSM doit être ouvert avec l\'option de télécommande "Contrôle à distance" activée dans ses paramètres (accédez-y avec F12)' ) ;
} ) ;
} ) ;
2025-04-18 16:50:26 +02:00
2025-05-01 12:38:48 +02:00
$ ( '#searchButton' ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
searchLocation ( ) ;
} ) ;
$ ( '#searchLocation' ) . on ( 'keydown' , function ( e ) {
if ( e . key === 'Enter' ) {
e . preventDefault ( ) ;
searchLocation ( ) ;
}
} ) ;
2025-04-28 11:20:11 +02:00
$ ( '#shareUrl' ) . on ( 'click' , copyCurrentUrl ) ;
$ ( '#filter_max_output' ) . on ( 'input' , function ( ) {
const value = $ ( this ) . val ( ) ;
console . log ( 'filter_max_output' , value , $ ( this ) ) ;
$ ( '#filter_max_output_display' ) . text ( value + ' kW' ) ;
refreshDisplay ( ) ;
} ) ;
$ ( '#filter_max_output_slider' ) . on ( 'input' , function ( ) {
const value = $ ( this ) . val ( ) ;
2025-04-18 17:53:07 +02:00
2025-04-28 11:20:11 +02:00
lcm _config . filter _max _output _default _value = value ;
$ ( '#filter_max_output_display' ) . text ( value + ' kW' ) ;
refreshDisplay ( ) ;
} ) ;
2025-04-18 17:53:07 +02:00
2025-04-28 11:20:11 +02:00
$ ( '#searchResults' ) . on ( 'change' , function ( ) {
const selectedIndex = $ ( this ) . eq ( 0 ) . val ( ) ;
if ( selectedIndex !== null ) {
const selectedPlace = $ ( this ) . find ( 'option:selected' ) . data ( 'place' ) ;
moveToLocation ( selectedPlace ) ;
}
2025-04-18 17:53:07 +02:00
} ) ;
2025-04-28 11:20:11 +02:00
osmose _markers . addTo ( map ) ;
2025-05-01 12:28:43 +02:00
$ ( '#average_charge_kwh' ) . val ( averageChargeKwh ) ;
$ ( '#average_charge_kwh' ) . on ( 'input' , function ( ) {
averageChargeKwh = parseFloat ( $ ( this ) . val ( ) ) || 26 ;
// Si un détail de station est affiché, le mettre à jour
if ( $ ( '#current_station_infos' ) . data ( 'currentFeature' ) ) {
fillDetailsWithFeature ( $ ( '#current_station_infos' ) . data ( 'currentFeature' ) ) ;
}
} ) ;
2024-12-28 17:59:15 +01:00
}
2024-12-28 22:43:18 +01:00
2024-12-28 17:59:15 +01:00
function copyCurrentUrl ( ) {
2025-02-03 13:41:48 +01:00
const url = window . location . href ;
2024-12-28 17:59:15 +01:00
var dummy = document . createElement ( 'input' ) ,
2025-02-03 13:41:48 +01:00
text = window . location . href ;
2024-12-28 17:59:15 +01:00
document . body . appendChild ( dummy ) ;
dummy . value = text ;
dummy . select ( ) ;
document . execCommand ( 'copy' ) ;
document . body . removeChild ( dummy ) ;
}
2025-04-18 16:50:26 +02:00
init ( )
// Créer un nouveau pane pour les marqueurs Osmose avec un zIndex plus élevé
map . createPane ( 'osmosePane' ) ;
2025-04-20 00:54:04 +02:00
map . getPane ( 'osmosePane' ) . style . zIndex = 1000 ;
// Ajouter une nouvelle fonction pour mettre à jour le compteur de stations filtrées
function updateFilteredStationsCount ( ) {
const totalStations = geojsondata ? geojsondata . features . length : 0 ;
const filterStats = ` <div class="filter-stats"> ${ displayedStationsCount } stations sur ${ totalStations } trouvées</div> ` ;
// Mettre à jour ou créer l'élément après le slider
let existingStats = $ ( '.filter-stats' ) ;
if ( existingStats . length ) {
existingStats . replaceWith ( filterStats ) ;
} else {
$ ( '#filter_max_output_display' ) . after ( filterStats ) ;
}
}