1/* 2 * Nova OSM 3 * 4 * Copyright (c) Inovagora 5 * www.inovagora.net 6 * 7 * Version: 1.3.1 8 */ 9( function ( $ ) { 10 11 $.fn.osm = function ( options ) { 12 13 this.$canvas = $( this ) 14 this.$markers = this.$canvas.find( '.marker' ) 15 16 17 this.throttle = function(callback, delay) { 18 var last; 19 var timer; 20 return function () { 21 var context = this; 22 var now = +new Date(); 23 var args = arguments; 24 if (last && now < last + delay) { 25 // le délai n'est pas écoulé on reset le timer 26 clearTimeout(timer); 27 timer = setTimeout(function () { 28 last = now; 29 callback.apply(context, args); 30 }, delay); 31 } else { 32 last = now; 33 callback.apply(context, args); 34 } 35 }; 36 } 37 38 this.debounce = function(callback, delay){ 39 var timer; 40 return function(){ 41 var args = arguments; 42 var context = this; 43 clearTimeout(timer); 44 timer = setTimeout(function(){ 45 callback.apply(context, args); 46 }, delay) 47 } 48 } 49 50 this.initialize = function () { 51 52 var defaults_settings = { 53 zoom: 14, 54 lat: '', 55 lng: '', 56 paddingBreakpoint: 1200, // Point de rupture à partir duquel le padding est pris en compte (en px) 57 padding: [40, 40, 40, 40], // Padding interne Top, Right, Bottom, Left 58 markerCluster: true, // Activer le rassemblement des points 59 markers: {}, // Liste des marqueurs 60 mapboxToken: '', // Clé d'API Mapbox, 61 forceTileLayer: '', // URL d'un layeur custom 62 disableScrollZoom: true, // Désactive le zoom au scroll (true par défaut) 63 }; 64 65 this.settings = $.extend( {}, defaults_settings, options ); 66 67 if ( typeof L.markerClusterGroup !== 'function' ) { 68 this.settings.markerCluster = false; 69 } 70 71 this.settings.padding = { 72 top: this.settings.padding[ 0 ], 73 right: this.settings.padding[ 1 ], 74 bottom: this.settings.padding[ 2 ], 75 left: this.settings.padding[ 3 ], 76 } 77 78 this.initializeMap(); 79 80 return this; 81 } 82 83 84 // Initialize the map 85 this.initializeMap = function () { 86 87 // Vars 88 var self = this, 89 map, 90 promises = []; 91 92 // renderMap = L.map(this).fitWorld(); 93 map = L.map( self[ 0 ] ) 94 95 if ( this.settings.lat != '' && this.settings.lng != '' ) { 96 var latLng = this.newLatLng( parseFloat( this.settings.lat ), parseFloat( this.settings.lng ) );
97 map.setView( latLng, parseInt( this.settings.zoom ) ); 98 } 99 100 // Disable scroll zoom 101 if ( this.settings.disableScrollZoom == true ) { 102 map.scrollWheelZoom.disable(); 103 } 104 // Define Tile layer 105 // Official OSM tile layer (OSM) 106 var tileLayer = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; 107 108 // Mapbox tile layer 109 if ( this.settings.mapboxToken !== '' ) { 110 var tileLayer = 'https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}@2x?access_token=' + this.settings.mapboxToken; 111 } 112 113 /** 114 * Forced tile layer settings 115 * @since 1.1.0 116 */ 117 if ( this.settings.forceTileLayer !== '' ) { 118 var tileLayer = this.settings.forceTileLayer; 119 } 120 121 // Define attributions 122 var attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'; 123 124 // Set tile layer 125 L.tileLayer( tileLayer, { 126 attribution: attribution, 127 } ).addTo( map ); 128 129 // Add markers 130 map.markers = []; 131 map.bounds = []; 132 133 if ( self.settings.markerCluster ) { 134 map.clusterGroup = L.markerClusterGroup(); 135 } 136 137 for ( var i = 0; i < self.settings.markers.length; i++ ) { 138 promises = self.addMarker( map, self.settings.markers[i], promises ); 139 } 140 141 142 if ( self.settings.markerCluster ) { 143 map.addLayer( map.clusterGroup ); 144 } 145 146 // Add Events on map 147 self.addMapEvents( map ); 148 149 // reference 150 self.map = map; 151 152 if ( this.settings.lat == '' || this.settings.lng == '' ) { 153 Promise.all( promises ).then( function ( data ) { 154 // center the map 155 self.center(); 156 157 setTimeout( function () { 158 if ( typeof map.markers[0] != 'undefined' && map.markers.length == 1 ) { 159 map.markers[0].openPopup() 160 } 161 }, 1000 ); 162 }); 163 } 164 165 } 166 167 this.newLatLng = function ( lat, lng ) { 168 return L.latLng( parseFloat( lat ), parseFloat( lng ) ); 169 }, 170 171 this.getWindowSize = function () { 172 var w = window, 173 d = document, 174 e = d.documentElement, 175 g = d.getElementsByTagName( 'body' )[ 0 ], 176 x = w.innerWidth || e.clientWidth || g.clientWidth, 177 y = w.innerHeight|| e.clientHeight|| g.clientHeight; 178 return { 179 width: x, 180 height: y 181 } 182 }, 183 184 this.addMarker = function ( map, marker, promises ) { 185 186 var self = this, 187 bounds; 188 189 // Defaults settings for marker 190 var marker_defaults_settings = { 191 file: '', 192 lat: '', 193 lng: '', 194 html: '', 195 hoverSelector: '', 196 iconUrl: '', 197 iconActiveUrl: '', 198 shadowUrl: '', 199 shadowActiveUrl: '', 200 iconSize: [32,37], 201 tooltip: '', // Activate tooltip on hover if set 202 href: '', // Activate open window on click if not empty 203 hrefTarget: '', // window target option if href is not empty 204 }; 205 206 marker = $.extend( {}, marker_defaults_settings, marker ); 207 208 209 // Convert string to array for icon size 210 var advancedMarkersSettings = [ 211 'iconSize', 212 'iconActiveSize', 213 'shadowSize', 214 'shadowActiveSize', 215 'iconAnchor', 216 'iconActiveAnchor', 217 'shadowAnchor', 218 'shadowActiveAnchor', 219 'popupAnchor', 220 'popupActiveAnchor' 221 ]; 222 223 for ( var i = advancedMarkersSettings.length - 1; i >= 0; i-- ) { 224 if ( typeof marker[ advancedMarkersSettings[ i ] ] === 'string' ) { 225 marker[ advancedMarkersSettings[ i ] ] = marker[ advancedMarkersSettings[ i ] ].split( ',' ) 226 for ( var o = marker[ advancedMarkersSettings[ i ] ].length - 1; o >= 0; o-- ) { 227 marker[ advancedMarkersSettings[ i ] ][ o ] = parseInt( marker[ advancedMarkersSettings[ i ] ][ o ] ) 228 } 229 } 230 } 231 232 233 234 // If file not empty 235 if ( marker.file !== '' ) { 236 var extension = marker.file.split( '.' ).pop() 237 238 // if filetype is kmz 239 if ( extension == 'kmz' ) { 240 241 var kmz = marker.file; 242 243 promises.push( 244 fetch( kmz ) // On récupère le fichier kmz 245 .then( function ( response ) { 246 if ( response.status === 200 || response.status === 0 ) { 247 return Promise.resolve( response.blob() ); 248 } else { 249 return Promise.reject( new Error( response.statusText ) ); 250 } 251 }) 252 .then( JSZip.loadAsync ) 253 .then( function ( zip ) { 254 var kml = ''; 255 var zipPromises = []; 256 var imgFormats = [ 'jpg', 'jpeg', 'png', 'gif', 'svg' ]; 257
258 zip.forEach( function ( relativePath, file ) { 259 var extension = relativePath.split( '.' ).pop(); 260 if ( extension == 'kml' ) { 261 262 zipPromises.push( 263 zip.file( relativePath ).async( 'string' ).then( function ( kml ) { 264 var imgPromises = []; 265 var editedKml = kml; 266 267 zip.forEach( function ( relativePath, file ) { 268 var extension = relativePath.split( '.' ).pop(); 269 var mimetype = ''; 270 271 if ( imgFormats.indexOf( extension ) ) { 272 273 if ( extension == 'jpg' ) { 274 mimetype = 'image/jpeg'; 275 } else if ( extension == 'svg' ) { 276 mimetype = 'image/svg+xml'; 277 } else { 278 mimetype = 'image/' + extension; 279 } 280 281 imgPromises.push( 282 zip.file( relativePath ).async( 'base64' ).then( function ( content ) { 283 editedKml = editedKml.replace( relativePath, 'data:' + mimetype + ';base64,' + content ) 284 }) 285 ); 286 } 287 }); 288 return Promise.all( imgPromises ).then( function ( data ) { 289 // console.log( 'kmz : mise en place terminée') 290 return editedKml; 291 }); 292 }) 293 ) 294 } 295 }); 296 297 return Promise.all( zipPromises ).then( function ( data ) { 298 return data[ 0 ] 299 }); 300 301 }) 302 .then( function success( kml ) { 303 304 var parser = new DOMParser(); 305 kml = parser.parseFromString( kml, 'text/xml'); 306 307 // Replace https, www, email with link 308 for (var i = kml.getElementsByTagName('description').length - 1; i >= 0; i--) { 309 kml.getElementsByTagName('description')[i].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 310 } 311 312 var track = new L.KML( kml ) 313 314 if ( marker.html !== '' ) { 315 $.each( track._layers, function(index, val) { 316 val.bindPopup( marker.html ); 317 }); 318 } 319 320 // Add to markerCluster if enable 321 if ( self.settings.markerCluster ) { 322 map.clusterGroup.addLayer( track ); 323 } else { 324 track.addTo( map ); 325 } 326 327 // get bounds of layer 328 bounds = track.getBounds() 329 330 // Adding coordinates to bounds
331 map.bounds.push( bounds.getNorthEast() ); 332 map.bounds.push( bounds.getSouthWest() ); 333 334 // map.fitBounds( bounds ) 335 336 }, function error( e ) { 337 console.log( 'Une erreur est survenue sur l\'affichage d\'un kmz' ); 338 }) 339 ) 340 341 } else if ( extension == 'kml' ) { 342 343 promises.push( 344 fetch( marker.file ) 345 .then( function ( response ) { 346 return response.text() 347 }) 348 .then( function( kml ) { 349 350 var parser = new DOMParser(); 351 kml = parser.parseFromString( kml, 'text/xml' ); 352 353 // Replace https, www, email with link 354 for ( var i = kml.getElementsByTagName( 'description' ).length - 1; i >= 0; i-- ) { 355 kml.getElementsByTagName( 'description' )[ i ].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 356 } 357 358 // Create new kml overlay 359 var track = new L.KML( kml ) 360 361 if ( marker.html !== '' ) { 362 $.each( track._layers, function(index, val) { 363 val.bindPopup( marker.html ); 364 }); 365 } 366 367 // Add to markerCluster if enable 368 if ( self.settings.markerCluster ) { 369 map.clusterGroup.addLayer( track ); 370 } else { 371 track.addTo( map ); 372 } 373 374 // get bounds of layer 375 bounds = track.getBounds() 376 377 // Adding coordinates to bounds
378 map.bounds.push( bounds.getNorthEast() ); 379 map.bounds.push( bounds.getSouthWest() ); 380 381 // @todo: Wait for all before centering 382 // map.fitBounds( bounds ) 383 }) 384 ) 385 386 } else if ( extension == 'geojson' ) { 387 388 promises.push( 389 fetch( marker.file ) 390 .then( function ( response ) { 391 return response.json() 392 }) 393 .then( function( data ) { 394 395 // Add geoJson 396 var track = new L.geoJSON( data, { 397 onEachFeature: function ( feature, layer ) { 398 399 if ( feature.properties && ( feature.properties.name || feature.properties.nom || feature.properties.popupContent ) ) { 400 var content = '<div class="infowindow">'; 401 content += '<div class="infowindow-body">'; 402 403 if ( feature.properties.name ) { 404 content += '<h3 class="infowindow-title">' + feature.properties.name + '</h3>'; 405 } 406 407 if ( feature.properties.nom ) { 408 content += '<h3 class="infowindow-title">' + feature.properties.nom + '</h3>'; 409 } 410 411 if ( feature.properties.popupContent ) { 412 content += '<div class="infowindow-text">' + feature.properties.popupContent + '</div>'; 413 } 414 415 content += '</div>'; 416 content += '</div>'; 417 418 if ( content !== '' ) { 419 layer.bindPopup( content ); 420 } 421 422 } 423 } 424 } ) 425 426 // Add to markerCluster if enable 427 if ( self.settings.markerCluster ) { 428 map.clusterGroup.addLayer( track ); 429 } else { 430 track.addTo( map ); 431 } 432 433 // get bounds of layer 434 bounds = track.getBounds() 435 436 // Adding coordinates to bounds
437 map.bounds.push( bounds.getNorthEast() ); 438 map.bounds.push( bounds.getSouthWest() ); 439 440 }) 441 ) 442 443 } 444 445 } 446 447 448 if ( marker.lat !== '' && marker.lng !== '' ) { 449 450 var latLng = self.newLatLng( parseFloat( marker.lat ), parseFloat( marker.lng ) ), 451 new_marker; 452 453 454 if ( marker.iconUrl !== '' ) { 455 456 var iconSettings = { 457 iconUrl: marker.iconUrl, 458 iconSize: marker.iconSize, // size of the icon 459 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 460 popupAnchor: ( marker.popupAnchor != undefined && marker.popupAnchor !== '' ) ? marker.popupAnchor : [ 0, ( marker.iconSize[ 1 ] * -1 ) ] // point from which the popup should open relative to the iconAnchor 461 }; 462 463 if ( marker.shadowUrl != undefined && marker.shadowUrl !== '' ) { 464 iconSettings.shadowUrl = marker.shadowUrl; 465 } 466 467 if ( marker.shadowSize != undefined && marker.shadowSize !== '' ) { 468 iconSettings.shadowSize = marker.shadowSize; 469 } 470 471 if ( marker.shadowAnchor != undefined && marker.shadowAnchor !== '' ) { 472 iconSettings.shadowAnchor = marker.shadowAnchor; 473 } 474 475 var icon = L.icon( iconSettings ); 476 477 new_marker = L.marker( latLng, { icon: icon } ); 478 479 } else { 480 481 new_marker = L.marker( latLng ); 482 483 } 484 485 if ( marker.html !== '' ) { 486 new_marker.bindPopup( marker.html, { 487 maxWidth: 600 488 } ); 489 } 490 491 if ( marker.tooltip !== '' ) { 492 new_marker.on( 'mouseover', function ( e ) { 493 self.showTooltip( new_marker, marker.tooltip ) 494 } ); 495 } 496 497 if ( marker.href !== '' ) { 498 new_marker.on( 'click', function () { 499 var target = '_self'; 500 if ( marker.hrefTarget != '' ) { 501 target = marker.hrefTarget; 502 } 503 window.open( marker.href, target ); 504 } ); 505 } 506 507 508 if ( marker.hoverSelector !== '' && marker.iconActiveUrl !== '' ) { 509 510 var icon = new_marker.getIcon(); 511 512 if ( $( marker.hoverSelector ).length ) { 513 $( marker.hoverSelector ) 514 .on( 'mouseenter', function () { 515 516 var iconSettings = { 517 iconUrl: marker.iconActiveUrl, 518 }; 519 520 521 if ( marker.iconActiveSize != undefined && marker.iconActiveSize !== '' ) { 522 iconSettings.iconSize = marker.iconActiveSize; 523 524 if ( marker.iconActiveAnchor != undefined && marker.iconActiveAnchor !== '' ) { 525 iconSettings.iconAnchor = marker.iconActiveAnchor; 526 } else { 527 iconSettings.iconAnchor = [ marker.iconActiveSize[ 0 ] / 2, marker.iconActiveSize[ 1 ] ]; 528 } 529 530 if ( marker.popupActiveAnchor != undefined && marker.popupActiveAnchor !== '' ) { 531 iconSettings.popupAnchor = marker.popupActiveAnchor; 532 } else { 533 iconSettings.popupAnchor = [ 0, ( marker.iconActiveSize[ 1 ] * -1 ) ]; 534 } 535 536 } else { 537 iconSettings.iconSize = marker.iconSize; 538 539 if ( marker.iconActiveAnchor != undefined && marker.iconActiveAnchor !== '' ) { 540 iconSettings.iconAnchor = marker.iconActiveAnchor; 541 } else { 542 iconSettings.iconAnchor = [ marker.iconSize[ 0 ] / 2, marker.iconSize[ 1 ] ]; 543 } 544 545 if ( marker.popupActiveAnchor != undefined && marker.popupActiveAnchor !== '' ) { 546 iconSettings.popupAnchor = marker.popupActiveAnchor; 547 } else { 548 iconSettings.popupAnchor = [ 0, ( marker.iconSize[ 1 ] * -1 ) ]; 549 } 550 } 551 552 553 if ( marker.shadowActiveUrl != undefined && marker.shadowActiveUrl !== '' ) { 554 iconSettings.shadowActiveUrl = marker.shadowActiveUrl; 555 } 556 557 if ( marker.shadowActiveSize != undefined && marker.shadowActiveSize !== '' ) { 558 iconSettings.shadowActiveSize = marker.shadowActiveSize; 559 } 560 561 if ( marker.shadowActiveAnchor != undefined && marker.shadowActiveAnchor !== '' ) { 562 iconSettings.shadowActiveAnchor = marker.shadowActiveAnchor; 563 } 564 565 var activeIcon = L.icon( iconSettings ); 566 567 new_marker.setIcon( activeIcon ) 568 569 new_marker._icon.classList.add( 'active' ) 570 571 }) 572 .on( 'mouseleave', function () { 573 574 new_marker._icon.classList.remove( 'active' ) 575 576 new_marker.setIcon( icon ) 577 578 }); 579 } 580 581 } 582 583 584 map.bounds.push( [ marker.lat, marker.lng ] ); 585 map.markers.push( new_marker ); 586 587 588 // Add to markerCluster if enable 589 if ( self.settings.markerCluster ) { 590 map.clusterGroup.addLayer( new_marker ); 591 } else { 592 new_marker.addTo( map ); 593 } 594 } 595 596 597 if ( typeof marker.polyline != 'undefined' && marker.polyline !== '' ) { 598 var polyline = L.polyline( marker.polyline ).addTo( map ); 599 600 // get bounds of layer 601 bounds = polyline.getBounds() 602 603 // Adding coordinates to bounds
604 map.bounds.push( bounds.getNorthEast() ); 605 map.bounds.push( bounds.getSouthWest() ); 606 607 } 608 609 if ( typeof marker.polygon != 'undefined' && marker.polygon !== '' ) { 610 var polygon = L.polygon( marker.polygon, {color: 'red'} ).addTo( map ); 611 612 // get bounds of layer 613 bounds = polygon.getBounds() 614 615 // Adding coordinates to bounds 616 map.bounds.push( bounds.getNorthEast() ); 617 map.bounds.push( bounds.getSouthWest() ); 618 619 } 620 621 622 return promises; 623 624 } 625 626 this.showTooltip = function ( marker, content ) { 627 marker.unbindTooltip(); 628 if ( ! marker.isPopupOpen() ) { 629 marker.bindTooltip( content, { 630 direction: 'top', 631 } ).openTooltip(); 632 } 633 } 634 635 // Add event on map (for popup) 636 this.addMapEvents = function ( map ) { 637 var self = this; 638 639 // Center popup on opening 640 map.on( 'popupopen', function ( e ) { 641 var px = map.project( e.popup._latlng ); // find the pixel location on the map where the popup anchor is 642 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 643 644 645 if ( self.getWindowSize().width > parseInt( self.settings.paddingBreakpoint ) ) { 646 px.x = px.x - ( self.settings.padding.left / 2 ) + ( self.settings.padding.right / 2 ) 647 px.y = px.y - ( self.settings.padding.top / 2 ) + ( self.settings.padding.bottom / 2 ) 648 } 649 650 map.panTo( map.unproject( px ), { animate: true } ); // pan to new center 651 }); 652 653 $( window ).on( 'resize', self.debounce( function ( e ) { 654 if ( self.settings.lat != '' && self.settings.lng != '' ) { 655 map.panTo( new L.LatLng( parseFloat( self.settings.lat ), parseFloat( self.settings.lng ) ) ); 656 } else { 657 self.center(); 658 } 659 }, 150 ) ); 660 661 } 662 663 // Center the map on markers 664 this.center = function () { 665 var self = this; 666 667 if ( self.map.bounds.length ) { 668 bounds = new L.LatLngBounds( self.map.bounds ); 669 670 if ( self.getWindowSize().width > parseInt( self.settings.paddingBreakpoint ) ) { 671 self.map.fitBounds(bounds, { 672 paddingTopLeft: [ self.settings.padding.left, self.settings.padding.top ], 673 paddingBottomRight: [ self.settings.padding.right, self.settings.padding.bottom ], 674 maxZoom: this.settings.zoom, 675 } ); 676 } else { 677 self.map.fitBounds( bounds, { maxZoom : this.settings.zoom } ); 678 } 679 } 680 } 681 682 // Center the map on markers 683 this.refresh = function () { 684 var self = this; 685 686 // à utiliser après le resize 687 self.map.invalidateSize( true ); 688 // self.center(); 689 } 690 691 this.linkify = function ( inputText ) { 692 var replacedText, replacePattern1, replacePattern2, replacePattern3; 693 694 //URLs starting with http://, https://, or ftp:// 695 replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
696 replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>'); 697 698 //URLs starting with "www." (without // before it, or it'd re-link the ones done above). 699 replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 700 replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>'); 701 702 //Change email addresses to mailto:: links. 703 replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; 704 replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>'); 705 706 return replacedText; 707 } 708 709 return this.initialize(); 710 }; 711 712}( 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.