1/* 2 * Nova OSM 3 * 4 * Copyright (c) Inovagora 5 * www.inovagora.net 6 * 7 * Version: 1.3.0 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 } 158 159 } 160 161 this.newLatLng = function ( lat, lng ) { 162 return L.latLng( parseFloat( lat ), parseFloat( lng ) ); 163 }, 164 165 this.getWindowSize = function () { 166 var w = window, 167 d = document, 168 e = d.documentElement, 169 g = d.getElementsByTagName( 'body' )[ 0 ], 170 x = w.innerWidth || e.clientWidth || g.clientWidth, 171 y = w.innerHeight|| e.clientHeight|| g.clientHeight; 172 return { 173 width: x, 174 height: y 175 } 176 }, 177 178 this.addMarker = function ( map, marker, promises ) { 179 180 var self = this, 181 bounds; 182 183 // Defaults settings for marker 184 var marker_defaults_settings = { 185 file: '', 186 lat: '', 187 lng: '', 188 html: '', 189 iconUrl: '', 190 iconActiveUrl: '', 191 hoverSelector: '', 192 iconSize: [32,37], 193 tooltip: '', // Activate tooltip on hover if set 194 href: '', // Activate open window on click if not empty 195 hrefTarget: '', // window target option if href is not empty 196 // iconAnchor: [0,0], 197 // popupAnchor: [0,0], 198 }; 199 200 marker = $.extend( {}, marker_defaults_settings, marker ); 201 202 // Convert string to array for icon size 203 if ( typeof marker.iconSize === 'string' ) { 204 marker.iconSize = marker.iconSize.split( ',' ) 205 } 206 207 // If file not empty 208 if ( marker.file !== '' ) { 209 var extension = marker.file.split( '.' ).pop() 210 211 // if filetype is kmz 212 if ( extension == 'kmz' ) { 213 214 var kmz = marker.file; 215 216 promises.push( 217 fetch( kmz ) // On récupère le fichier kmz 218 .then( function ( response ) { 219 if ( response.status === 200 || response.status === 0 ) { 220 return Promise.resolve( response.blob() ); 221 } else { 222 return Promise.reject( new Error( response.statusText ) ); 223 } 224 }) 225 .then( JSZip.loadAsync ) 226 .then( function ( zip ) { 227 var kml = ''; 228 var zipPromises = []; 229 var imgFormats = [ 'jpg', 'jpeg', 'png', 'gif', 'svg' ]; 230 231 zip.forEach( function ( relativePath, file ) { 232 var extension = relativePath.split( '.' ).pop(); 233 if ( extension == 'kml' ) { 234 235 zipPromises.push( 236 zip.file( relativePath ).async( 'string' ).then( function ( kml ) { 237 var imgPromises = []; 238 var editedKml = kml; 239 240 zip.forEach( function ( relativePath, file ) { 241 var extension = relativePath.split( '.' ).pop(); 242 var mimetype = ''; 243 244 if ( imgFormats.indexOf( extension ) ) { 245 246 if ( extension == 'jpg' ) { 247 mimetype = 'image/jpeg'; 248 } else if ( extension == 'svg' ) { 249 mimetype = 'image/svg+xml'; 250 } else { 251 mimetype = 'image/' + extension; 252 } 253 254 imgPromises.push( 255 zip.file( relativePath ).async( 'base64' ).then( function ( content ) { 256 editedKml = editedKml.replace( relativePath, 'data:' + mimetype + ';base64,' + content ) 257 }) 258 ); 259 } 260 }); 261 return Promise.all( imgPromises ).then( function ( data ) { 262 // console.log( 'kmz : mise en place terminée') 263 return editedKml; 264 }); 265 }) 266 ) 267 } 268 }); 269 270 return Promise.all( zipPromises ).then( function ( data ) { 271 return data[ 0 ] 272 }); 273 274 }) 275 .then( function success( kml ) { 276 277 var parser = new DOMParser(); 278 kml = parser.parseFromString( kml, 'text/xml'); 279 280 // Replace https, www, email with link 281 for (var i = kml.getElementsByTagName('description').length - 1; i >= 0; i--) { 282 kml.getElementsByTagName('description')[i].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 283 } 284 285 var track = new L.KML( kml ) 286 287 if ( marker.html !== '' ) { 288 $.each( track._layers, function(index, val) { 289 val.bindPopup( marker.html ); 290 }); 291 } 292 293 // Add to markerCluster if enable 294 if ( self.settings.markerCluster ) { 295 map.clusterGroup.addLayer( track ); 296 } else { 297 track.addTo( map ); 298 } 299 300 // get bounds of layer 301 bounds = track.getBounds() 302 303 // Adding coordinates to bounds
304 map.bounds.push( bounds.getNorthEast() ); 305 map.bounds.push( bounds.getSouthWest() ); 306 307 // map.fitBounds( bounds ) 308 309 }, function error( e ) { 310 console.log( 'Une erreur est survenue sur l\'affichage d\'un kmz' ); 311 }) 312 ) 313 314 } else if ( extension == 'kml' ) { 315 316 promises.push( 317 fetch( marker.file ) 318 .then( function ( response ) { 319 return response.text() 320 }) 321 .then( function( kml ) { 322 323 var parser = new DOMParser(); 324 kml = parser.parseFromString( kml, 'text/xml' ); 325 326 // Replace https, www, email with link 327 for ( var i = kml.getElementsByTagName( 'description' ).length - 1; i >= 0; i-- ) { 328 kml.getElementsByTagName( 'description' )[ i ].textContent = self.linkify( kml.getElementsByTagName('description')[i].textContent ) 329 } 330 331 // Create new kml overlay 332 var track = new L.KML( kml ) 333 334 if ( marker.html !== '' ) { 335 $.each( track._layers, function(index, val) { 336 val.bindPopup( marker.html ); 337 }); 338 } 339 340 // Add to markerCluster if enable 341 if ( self.settings.markerCluster ) { 342 map.clusterGroup.addLayer( track ); 343 } else { 344 track.addTo( map ); 345 } 346 347 // get bounds of layer 348 bounds = track.getBounds() 349 350 // Adding coordinates to bounds
351 map.bounds.push( bounds.getNorthEast() ); 352 map.bounds.push( bounds.getSouthWest() ); 353 354 // @todo: Wait for all before centering 355 // map.fitBounds( bounds ) 356 }) 357 ) 358 359 } else if ( extension == 'geojson' ) { 360 361 promises.push( 362 fetch( marker.file ) 363 .then( function ( response ) { 364 return response.json() 365 }) 366 .then( function( data ) { 367 368 // Add geoJson 369 var track = new L.geoJSON( data, { 370 onEachFeature: function ( feature, layer ) { 371 372 if ( feature.properties && ( feature.properties.name || feature.properties.nom || feature.properties.popupContent ) ) { 373 var content = '<div class="infowindow">'; 374 content += '<div class="infowindow-body">'; 375 376 if ( feature.properties.name ) { 377 content += '<h3 class="infowindow-title">' + feature.properties.name + '</h3>'; 378 } 379 380 if ( feature.properties.nom ) { 381 content += '<h3 class="infowindow-title">' + feature.properties.nom + '</h3>'; 382 } 383 384 if ( feature.properties.popupContent ) { 385 content += '<div class="infowindow-text">' + feature.properties.popupContent + '</div>'; 386 } 387 388 content += '</div>'; 389 content += '</div>'; 390 391 if ( content !== '' ) { 392 layer.bindPopup( content ); 393 } 394 395 } 396 } 397 } ) 398 399 // Add to markerCluster if enable 400 if ( self.settings.markerCluster ) { 401 map.clusterGroup.addLayer( track ); 402 } else { 403 track.addTo( map ); 404 } 405 406 // get bounds of layer 407 bounds = track.getBounds() 408 409 // Adding coordinates to bounds
410 map.bounds.push( bounds.getNorthEast() ); 411 map.bounds.push( bounds.getSouthWest() ); 412 413 }) 414 ) 415 416 } 417 418 } 419 420 421 if ( marker.lat !== '' && marker.lng !== '' ) { 422 423 var latLng = self.newLatLng( parseFloat( marker.lat ), parseFloat( marker.lng ) ), 424 new_marker; 425 426 427 if ( marker.iconUrl !== '' ) { 428 429 var icon = L.icon( { 430 iconUrl: marker.iconUrl, 431 iconSize: [marker.iconSize[ 0 ], marker.iconSize[ 1 ] ], // size of the icon 432 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 433 popupAnchor: ( marker.popupAnchor != undefined && marker.popupAnchor !== '' ) ? marker.popupAnchor : [ 0, ( marker.iconSize[ 1 ] * -1 ) ] // point from which the popup should open relative to the iconAnchor 434 } ); 435 436 new_marker = L.marker( latLng, { icon: icon } ); 437 } else { 438 new_marker = L.marker( latLng ); 439 } 440 441 if ( marker.html !== '' ) { 442 new_marker.bindPopup( marker.html, { 443 maxWidth: 600 444 } ); 445 } 446 447 if ( marker.tooltip !== '' ) { 448 new_marker.on( 'mouseover', function ( e ) { 449 self.showTooltip( new_marker, marker.tooltip ) 450 } ); 451 } 452 453 if ( marker.href !== '' ) { 454 new_marker.on( 'click', function () { 455 var target = '_self'; 456 if ( marker.hrefTarget != '' ) { 457 target = marker.hrefTarget; 458 } 459 window.open( marker.href, target ); 460 } ); 461 } 462 463 464 if ( marker.hoverSelector !== '' && marker.iconActiveUrl !== '' ) { 465 466 var icon = new_marker.getIcon(); 467 468 if ( $( marker.hoverSelector ).length ) { 469 $( marker.hoverSelector ) 470 .on( 'mouseenter', function () { 471 472 var activeIcon = L.icon({ //add this new icon 473 iconUrl: marker.iconActiveUrl, 474 }); 475 476 new_marker.setIcon( activeIcon ) 477 }) 478 .on('mouseleave', function () { 479 480 new_marker.setIcon( icon ) 481 }); 482 } 483 484 } 485 486 487 488 map.bounds.push( [ marker.lat, marker.lng ] ); 489 map.markers.push( new_marker ); 490 491 492 // Add to markerCluster if enable 493 if ( self.settings.markerCluster ) { 494 map.clusterGroup.addLayer( new_marker ); 495 } else { 496 new_marker.addTo( map ); 497 } 498 } 499 500 501 if ( typeof marker.polyline != 'undefined' && marker.polyline !== '' ) { 502 var polyline = L.polyline( marker.polyline ).addTo( map ); 503 504 // get bounds of layer 505 bounds = polyline.getBounds() 506 507 // Adding coordinates to bounds
508 map.bounds.push( bounds.getNorthEast() ); 509 map.bounds.push( bounds.getSouthWest() ); 510 511 } 512 513 if ( typeof marker.polygon != 'undefined' && marker.polygon !== '' ) { 514 var polygon = L.polygon( marker.polygon, {color: 'red'} ).addTo( map ); 515 516 // get bounds of layer 517 bounds = polygon.getBounds() 518 519 // Adding coordinates to bounds 520 map.bounds.push( bounds.getNorthEast() ); 521 map.bounds.push( bounds.getSouthWest() ); 522 523 } 524 525 526 return promises; 527 528 } 529 530 this.showTooltip = function ( marker, content ) { 531 marker.unbindTooltip(); 532 if ( ! marker.isPopupOpen() ) { 533 marker.bindTooltip( content, { 534 direction: 'top', 535 } ).openTooltip(); 536 } 537 } 538 539 // Add event on map (for popup) 540 this.addMapEvents = function ( map ) { 541 var self = this; 542 543 // Center popup on opening 544 map.on( 'popupopen', function ( e ) { 545 var px = map.project( e.popup._latlng ); // find the pixel location on the map where the popup anchor is 546 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 547 548 549 if ( self.getWindowSize().width > parseInt( self.settings.paddingBreakpoint ) ) { 550 px.x = px.x - ( self.settings.padding.left / 2 ) + ( self.settings.padding.right / 2 ) 551 px.y = px.y - ( self.settings.padding.top / 2 ) + ( self.settings.padding.bottom / 2 ) 552 } 553 554 map.panTo( map.unproject( px ), { animate: true } ); // pan to new center 555 }); 556 557 $( window ).on( 'resize', self.debounce( function ( e ) { 558 if ( self.settings.lat != '' && self.settings.lng != '' ) { 559 map.panTo( new L.LatLng( parseFloat( self.settings.lat ), parseFloat( self.settings.lng ) ) ); 560 } else { 561 self.center(); 562 } 563 }, 150 ) ); 564 565 } 566 567 // Center the map on markers 568 this.center = function () { 569 var self = this; 570 571 if ( self.map.bounds.length ) { 572 bounds = new L.LatLngBounds( self.map.bounds ); 573 574 if ( self.getWindowSize().width > parseInt( self.settings.paddingBreakpoint ) ) { 575 self.map.fitBounds(bounds, { 576 paddingTopLeft: [ self.settings.padding.left, self.settings.padding.top ], 577 paddingBottomRight: [ self.settings.padding.right, self.settings.padding.bottom ], 578 maxZoom: this.settings.zoom, 579 } ); 580 } else { 581 self.map.fitBounds( bounds, { maxZoom : this.settings.zoom } ); 582 } 583 } 584 } 585 586 // Center the map on markers 587 this.refresh = function () { 588 var self = this; 589 590 // à utiliser après le resize 591 self.map.invalidateSize( true ); 592 // self.center(); 593 } 594 595 this.linkify = function ( inputText ) { 596 var replacedText, replacePattern1, replacePattern2, replacePattern3; 597 598 //URLs starting with http://, https://, or ftp:// 599 replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
600 replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>'); 601 602 //URLs starting with "www." (without // before it, or it'd re-link the ones done above). 603 replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 604 replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>'); 605 606 //Change email addresses to mailto:: links. 607 replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; 608 replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>'); 609 610 return replacedText; 611 } 612 613 return this.initialize(); 614 }; 615 616}( 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.