1/* 2 * Nova OSM 3 * 4 * Copyright (c) Inovagora 5 * www.inovagora.net 6 * 7 * Version: 1.1.2 8 */ 9( function ( $ ) { 10 11 $.fn.osm = function ( options ) { 12 13 this.$canvas = $( this ) 14 this.$markers = this.$canvas.find( '.marker' ) 15 16 this.initialize = function () { 17 18 var defaults_settings = { 19 zoom: 14, 20 lat: 0, 21 lng: 0, 22 paddingBreakpoint: false, // Point de rupture à partir duquel le padding est pris en compte (en px) 23 padding: [40, 40, 40, 40], // Padding interne Top, Right, Bottom, Left 24 markerCluster: true, // Activer le rassemblement des points 25 markers: {}, // Liste des marqueurs 26 mapboxToken: '', // Clé d'API Mapbox, 27 forceTileLayer: '', // URL d'un layeur custom 28 disableScrollZoom: true, // Désactive le zoom au scroll (true par défaut) 29 }; 30 31 this.settings = $.extend( {}, defaults_settings, options ); 32 33 if ( typeof L.markerClusterGroup !== 'function' ) { 34 this.settings.markerCluster = false; 35 } 36 37 this.settings.padding = { 38 top: this.settings.padding[ 0 ], 39 right: this.settings.padding[ 1 ], 40 bottom: this.settings.padding[ 2 ], 41 left: this.settings.padding[ 3 ], 42 } 43 44 this.initializeMap(); 45 46 return this; 47 } 48 49 50 // Initialize the map 51 this.initializeMap = function () { 52 53 // Vars 54 var self = this, 55 map, 56 latLng = self.newLatLng( self.settings.lat, self.settings.lng ); 57 promises = []; 58 59 // renderMap = L.map(this).fitWorld(); 60 map = L.map( self[ 0 ] ).setView( latLng, parseInt( self.settings.zoom ) ); 61 62 // Disable scroll zoom 63 if ( this.settings.disableScrollZoom == true ) { 64 map.scrollWheelZoom.disable(); 65 } 66 // Define Tile layer 67 // Official OSM tile layer (OSM) 68 var tileLayer = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; 69 70 // Mapbox tile layer 71 if ( this.settings.mapboxToken !== '' ) { 72 var tileLayer = 'https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}
72@2x?access_token=' + this.settings.mapboxToken; 73 } 74 75 /** 76 * Forced tile layer settings 77 * @since 1.1.0 78 */ 79 if ( this.settings.forceTileLayer !== '' ) { 80 var tileLayer = this.settings.forceTileLayer; 81 } 82 83 // Define attributions 84 var attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'; 85 86 // Set tile layer 87 L.tileLayer( tileLayer, { 88 attribution: attribution, 89 } ).addTo( map ); 90 91 // Add markers 92 map.markers = []; 93 map.bounds = []; 94 95 if ( self.settings.markerCluster ) { 96 map.clusterGroup = L.markerClusterGroup(); 97 } 98 99 for ( var i = 0; i < self.settings.markers.length; i++ ) { 100 promises = self.addMarker( map, self.settings.markers[i], promises ); 101 } 102 103 104 if ( self.settings.markerCluster ) { 105 map.addLayer( map.clusterGroup ); 106 } 107 108 // Add Events on map 109 self.addMapEvents( map ); 110 111 // reference 112 self.map = map; 113 114 115 Promise.all( promises ).then( function ( data ) { 116 // center the map 117 self.center(); 118 }); 119 120 } 121 122 this.newLatLng = function ( lat, lng ) { 123 return L.latLng( parseFloat( lat ), parseFloat( lng ) ); 124 }, 125 126 this.getWindowSize = function () { 127 var w = window, 128 d = document, 129 e = d.documentElement, 130 g = d.getElementsByTagName( 'body' )[ 0 ], 131 x = w.innerWidth || e.clientWidth || g.clientWidth, 132 y = w.innerHeight|| e.clientHeight|| g.clientHeight; 133 return { 134 width: x, 135 height: y 136 } 137 }, 138 139 this.addMarker = function ( map, marker, promises ) { 140 141 var self = this, 142 bounds; 143 144 // Defaults settings for marker 145 var marker_defaults_settings = { 146 file: '', 147 lat: '', 148 lng: '', 149 html: '', 150 iconUrl: '', 151 iconSize: [32,37], 152 // iconAnchor: [0,0], 153 // popupAnchor: [0,0], 154 }; 155 156 marker = $.extend( {}, marker_defaults_settings, marker ); 157 158 // Convert string to array for icon size 159 if ( typeof marker.iconSize === 'string' ) { 160 marker.iconSize = marker.iconSize.split( ',' ) 161 } 162 163 // If file not empty 164 if ( marker.file !== '' ) { 165 var extension = marker.file.split( '.' ).pop() 166 167 // if filetype is kmz 168 if ( extension == 'kmz' ) { 169 170 var kmz = marker.file; 171 172 promises.push( 173 fetch( kmz ) // On récupère le fichier kmz 174 .then( function ( response ) { 175 if ( response.status === 200 || response.status === 0 ) { 176 return Promise.resolve( response.blob() ); 177 } else { 178 return Promise.reject( new Error( response.statusText ) ); 179 } 180 }) 181 .then( JSZip.loadAsync ) 182 .then( function ( zip ) { 183 var kml = ''; 184 var zipPromises = []; 185 var imgFormats = [ 'jpg', 'jpeg', 'png', 'gif', 'svg' ]; 186 187 zip.forEach( function ( relativePath, file ) { 188 var extension = relativePath.split( '.' ).pop(); 189 if ( extension == 'kml' ) { 190 191 zipPromises.push( 192 zip.file( relativePath ).async( 'string' ).then( function ( kml ) { 193 var imgPromises = []; 194 var editedKml = kml; 195 196 zip.forEach( function ( relativePath, file ) { 197 var extension = relativePath.split( '.' ).pop(); 198 var mimetype = ''; 199 200 if ( imgFormats.indexOf( extension ) ) { 201 202 if ( extension == 'jpg' ) { 203 mimetype = 'image/jpeg'; 204 } else if ( extension == 'svg' ) { 205 mimetype = 'image/svg+xml'; 206 } else { 207 mimetype = 'image/' + extension; 208 } 209 210 imgPromises.push( 211 zip.file( relativePath ).async( 'base64' ).then( function ( content ) { 212 editedKml = editedKml.replace( relativePath, 'data:' + mimetype + ';base64,' + content ) 213 }) 214 ); 215 } 216 }); 217 return Promise.all( imgPromises ).then( function ( data ) { 218 // console.log( 'kmz : mise en place terminée') 219 return editedKml; 220 }); 221 }) 222 ) 223 } 224 }); 225 226 return Promise.all( zipPromises ).then( function ( data ) { 227 return data[ 0 ] 228 }); 229 230 }) 231 .then( function success( kml ) { 232 233 var parser = new DOMParser(); 234 kml = parser.parseFromString( kml, 'text/xml'); 235 236 // Replace https, www, email with link 237 for (var i = kml.getElementsByTagName('description').length - 1; i >= 0; i--) { 238 kml.getElementsByTagName('description')[i].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 239 } 240 241 var track = new L.KML( kml ) 242 243 // Add to markerCluster if enable 244 if ( self.settings.markerCluster ) { 245 map.clusterGroup.addLayer( track ); 246 } else { 247 track.addTo( map ); 248 } 249 250 // get bounds of layer 251 bounds = track.getBounds() 252 253 // Adding coordinates to bounds
254 map.bounds.push( bounds.getNorthEast() ); 255 map.bounds.push( bounds.getSouthWest() ); 256 257 // map.fitBounds( bounds ) 258 259 }, function error( e ) { 260 console.log( 'Une erreur est survenue sur l\'affichage d\'un kmz' ); 261 }) 262 ) 263 264 } else if ( extension == 'kml' ) { 265 266 promises.push( 267 fetch( marker.file ) 268 .then( function ( response ) { 269 return response.text() 270 }) 271 .then( function( kml ) { 272 273 var parser = new DOMParser(); 274 kml = parser.parseFromString( kml, 'text/xml' ); 275 276 // Replace https, www, email with link 277 for ( var i = kml.getElementsByTagName( 'description' ).length - 1; i >= 0; i-- ) { 278 kml.getElementsByTagName( 'description' )[ i ].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 279 } 280 281 // Create new kml overlay 282 var track = new L.KML( kml ) 283 284 // Add to markerCluster if enable 285 if ( self.settings.markerCluster ) { 286 map.clusterGroup.addLayer( track ); 287 } else { 288 track.addTo( map ); 289 } 290 291 // get bounds of layer 292 bounds = track.getBounds() 293 294 // Adding coordinates to bounds
295 map.bounds.push( bounds.getNorthEast() ); 296 map.bounds.push( bounds.getSouthWest() ); 297 298 // @todo: Wait for all before centering 299 // map.fitBounds( bounds ) 300 }) 301 ) 302 303 } else if ( extension == 'geojson' ) { 304 305 promises.push( 306 fetch( marker.file ) 307 .then( function ( response ) { 308 return response.json() 309 }) 310 .then( function( data ) { 311 312 // Add geoJson 313 var track = new L.geoJSON( data, { 314 onEachFeature: function ( feature, layer ) { 315 316 if ( feature.properties && ( feature.properties.name || feature.properties.nom || feature.properties.popupContent ) ) { 317 var content = '<div class="infowindow">'; 318 content += '<div class="infowindow-body">'; 319 320 if ( feature.properties.name ) { 321 content += '<h3 class="infowindow-title">' + feature.properties.name + '</h3>'; 322 } 323 324 if ( feature.properties.nom ) { 325 content += '<h3 class="infowindow-title">' + feature.properties.nom + '</h3>'; 326 } 327 328 if ( feature.properties.popupContent ) { 329 content += '<div class="infowindow-text">' + feature.properties.popupContent + '</div>'; 330 } 331 332 content += '</div>'; 333 content += '</div>'; 334 335 if ( content !== '' ) { 336 layer.bindPopup( content ); 337 } 338 339 } 340 } 341 } ) 342 343 // Add to markerCluster if enable 344 if ( self.settings.markerCluster ) { 345 map.clusterGroup.addLayer( track ); 346 } else { 347 track.addTo( map ); 348 } 349 350 // get bounds of layer 351 bounds = track.getBounds() 352 353 // Adding coordinates to bounds
354 map.bounds.push( bounds.getNorthEast() ); 355 map.bounds.push( bounds.getSouthWest() ); 356 357 }) 358 ) 359 360 } 361 362 } 363 364 if ( marker.lat !== '' && marker.lng !== '' ) { 365 366 var latLng = self.newLatLng( marker.lat, marker.lng ), 367 new_marker; 368 369 370 if ( marker.iconUrl !== '' ) { 371 372 var icon = L.icon( { 373 iconUrl: marker.iconUrl, 374 iconSize: [marker.iconSize[ 0 ], marker.iconSize[ 1 ] ], // size of the icon 375 iconAnchor: ( marker.iconAnchor != undefined && marker.iconAnchor !== '' ) ? marker.iconAnchor : [ marker.iconSize[ 0 ] / 2, marker.iconSize[ 1 ] ], // point from which the popup should open relative to the iconAnchor 376 popupAnchor: ( marker.popupAnchor != undefined && marker.popupAnchor !== '' ) ? marker.popupAnchor : [ 0, ( marker.iconSize[ 1 ] * -1 ) ] // point from which the popup should open relative to the iconAnchor 377 } ); 378 379 new_marker = L.marker( latLng, { icon: icon } ); 380 } else { 381 new_marker = L.marker( latLng ); 382 } 383 384 if ( marker.html !== '' ) { 385 new_marker.bindPopup( marker.html, { 386 maxWidth: 600 387 } ); 388 } 389 390 391 map.bounds.push( [ marker.lat, marker.lng ] ); 392 map.markers.push( new_marker ); 393 394 395 // Add to markerCluster if enable 396 if ( self.settings.markerCluster ) { 397 map.clusterGroup.addLayer( new_marker ); 398 } else { 399 new_marker.addTo( map ); 400 } 401 } 402 403 404 return promises; 405 406 } 407 408 // Add event on map (for popup) 409 this.addMapEvents = function ( map ) { 410 var self = this; 411 412 // Center popup on opening 413 map.on( 'popupopen', function ( e ) { 414 var px = map.project( e.popup._latlng ); // find the pixel location on the map where the popup anchor is 415 px.y -= e.popup._container.clientHeight / 2 // find the height of the popup container, divide by 2, subtract from the Y axis of marker location 416 417 418 if ( self.getWindowSize().width > self.settings.paddingBreakpoint ) { 419 px.x = px.x - ( self.settings.padding.left / 2 ) + ( self.settings.padding.right / 2 ) 420 px.y = px.y - ( self.settings.padding.top / 2 ) + ( self.settings.padding.bottom / 2 ) 421 } 422 423 map.panTo( map.unproject( px ), { animate: true } ); // pan to new center 424 }); 425 } 426 427 // Center the map on markers 428 this.center = function () { 429 var self = this; 430 431 if ( self.map.bounds.length ) { 432 bounds = new L.LatLngBounds( self.map.bounds ); 433 434 if ( self.getWindowSize().width > self.settings.paddingBreakpoint ) { 435 self.map.fitBounds(bounds, { 436 paddingTopLeft: [ self.settings.padding.left, self.settings.padding.top ], 437 paddingBottomRight: [ self.settings.padding.right, self.settings.padding.bottom ], 438 maxZoom: this.settings.zoom, 439 } ); 440 } else { 441 self.map.fitBounds( bounds, { maxZoom : this.settings.zoom } ); 442 } 443 } 444 } 445 446 // Center the map on markers 447 this.refresh = function () { 448 var self = this; 449 450 // à utiliser après le resize 451 self.map.invalidateSize( true ); 452 // self.center(); 453 } 454 455 this.linkify = function ( inputText ) { 456 var replacedText, replacePattern1, replacePattern2, replacePattern3; 457 458 //URLs starting with http://, https://, or ftp:// 459 replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
460 replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>'); 461 462 //URLs starting with "www." (without // before it, or it'd re-link the ones done above). 463 replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 464 replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>'); 465 466 //Change email addresses to mailto:: links. 467 replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; 468 replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>'); 469 470 return replacedText; 471 } 472 473 return this.initialize(); 474 }; 475 476}( jQuery ) )
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.