nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

westraPassesMarkers.js (11061B)


      1 import L from 'leaflet';
      2 import '~/lib/leaflet.layer.canvasMarkers';
      3 import {openPopupWindow} from '~/lib/popup-window';
      4 import escapeHtml from 'escape-html';
      5 import {saveAs} from '~/vendored/github.com/eligrey/FileSaver';
      6 import iconFromBackgroundImage from '~/lib/iconFromBackgroundImage';
      7 import {fetch} from '~/lib/xhr-promise';
      8 import {notify} from '~/lib/notifications';
      9 import * as logging from '~/lib/logging';
     10 
     11 const WestraPassesMarkers = L.Layer.CanvasMarkers.extend({
     12         options: {
     13             filePasses: 'westra_passes2.json',
     14             scaleDependent: true
     15         },
     16 
     17         initialize: function(baseUrl, options) {
     18             L.Layer.CanvasMarkers.prototype.initialize.call(this, null, options);
     19             this.on('markerclick', this.showPassDescription, this);
     20             this._baseUrl = baseUrl;
     21             this.url = baseUrl + this.options.filePasses;
     22         },
     23 
     24         loadData: async function() {
     25             if (this._downloadStarted) {
     26                 return;
     27             }
     28             this._downloadStarted = true;
     29             let xhr;
     30             try {
     31                 xhr = await fetch(this.url);
     32             } catch (e) {
     33                 this._downloadStarted = false;
     34                 logging.captureException(e, 'failed to get westra passes');
     35                 notify('Failed to get Westra passes data');
     36             }
     37 
     38             const {passes, regions} = JSON.parse(xhr.response);
     39             this.regions = regions;
     40             this._createMarkers(passes);
     41         },
     42 
     43         _createMarkers: function(passes) {
     44             const markers = [];
     45             for (const pass of passes) {
     46                 const marker = {
     47                     latlng: {
     48                         lat: pass.latlon[0],
     49                         lng: pass.latlon[1]
     50                     },
     51                     label: pass.name || "",
     52                     icon: this._makeIcon,
     53                     tooltip: this._makeTooltip.bind(this),
     54                     properties: pass
     55                 };
     56                 markers.push(marker);
     57             }
     58             this.addMarkers(markers);
     59             this._dataLoaded = true;
     60             this.fire('data-loaded');
     61         },
     62 
     63         onAdd: function(map) {
     64             L.Layer.CanvasMarkers.prototype.onAdd.call(this, map);
     65             this.loadData();
     66         },
     67 
     68         _makeTooltip: function(marker) {
     69             var properties = marker.properties,
     70                 toolTip = properties.grade || '';
     71             if (toolTip && properties.elevation) {
     72                 toolTip += ', ';
     73             }
     74             toolTip += properties.elevation || '';
     75             if (toolTip) {
     76                 toolTip = ' (' + toolTip + ')';
     77             }
     78             toolTip = (properties.name || 'без названия') + toolTip;
     79             toolTip = (properties.is_summit ? 'Вершина ' : 'Перевал ') + toolTip;
     80             return toolTip;
     81         },
     82 
     83         _passToGpx: function(marker) {
     84             let label = marker.tooltip;
     85             if (typeof label === 'function') {
     86                 label = label(marker);
     87             }
     88             label = escapeHtml(label);
     89             const gpx = `<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
     90                 <gpx xmlns="http://www.topografix.com/GPX/1/1"
     91                      creator="http://nakarte.me"
     92                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     93                      xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
     94                      version="1.1">
     95                     <wpt lat="${marker.latlng.lat.toFixed(6)}" lon="${marker.latlng.lng.toFixed(6)}">
     96                         <name>${label}</name>
     97                     </wpt>
     98                 </gpx>
     99             `;
    100             var filename = marker.properties.name || 'Без названия';
    101             saveAs(new Blob([gpx], {type: 'application/gpx+xml'}), filename + '.gpx', true);
    102         },
    103 
    104         _passToKml: function(marker) {
    105             let label = marker.tooltip;
    106             if (typeof label === 'function') {
    107                 label = label(marker);
    108             }
    109             label = escapeHtml(label);
    110             const kml = `<?xml version="1.0" encoding="UTF-8"?>
    111                 <kml xmlns="http://www.opengis.net/kml/2.2">
    112                     <Placemark>
    113                         <name>${label}</name>
    114                         <Point>
    115                             <coordinates>
    116                                 ${marker.latlng.lng.toFixed(6)},${marker.latlng.lat.toFixed(6)},0
    117                             </coordinates>
    118                         </Point>
    119                     </Placemark>
    120                 </kml>
    121             `;
    122             var filename = marker.properties.name || 'Без названия';
    123             saveAs(new Blob([kml], {type: 'application/vnd.google-earth.kml+xml'}), filename + '.kml', true);
    124         },
    125 
    126         _makeIcon: function(marker) {
    127             var className;
    128             className = 'westra-pass-marker ';
    129             if (marker.properties.is_summit) {
    130                 className += 'westra-pass-marker-summit';
    131             } else {
    132                 className += 'westra-pass-marker-' + marker.properties.grade_eng;
    133             }
    134             return iconFromBackgroundImage(className);
    135         },
    136 
    137         showPassDescription: function(e) {
    138             if (!this._map) {
    139                 return;
    140             }
    141             const properties = e.marker.properties,
    142                 latLng = e.marker.latlng,
    143                 catalogueUrlBase = 'https://westra.ru/passes',
    144                 passUrl = `${catalogueUrlBase}/Passes/${properties.id}`,
    145                 regionUrlBase = `${catalogueUrlBase}/Places`;
    146             let altnames = '',
    147                 connects = '',
    148                 comments = '';
    149             if (properties.altnames) {
    150                 altnames = `
    151                     <tr>
    152                         <td>Другие названия</td>
    153                         <td>${escapeHtml(properties.altnames)}</td>
    154                     </tr>`;
    155             }
    156 
    157             if (!properties.is_summit) {
    158                 connects = `
    159                     <tr>
    160                         <td>Соединяет</td>
    161                         <td>${properties.connects ? escapeHtml(properties.connects) : "неизвестнo"}</td>
    162                     </tr>`;
    163             }
    164 
    165             if (properties.comments) {
    166                 for (let comment of properties.comments) {
    167                     let user = '';
    168                     if (comment.user) {
    169                         user = (
    170                             `<span class="westra-passes-description-comment-author">${escapeHtml(comment.user)}:</span>`
    171                         );
    172                     }
    173                     comments += (
    174                         `<p class="westra-passes-description-comment">${user}${escapeHtml(comment.content)}</p>`
    175                     );
    176                 }
    177                 comments = `
    178                     <tr>
    179                         <td>Комментарии</td>
    180                         <td>${comments}</td>
    181                     </tr>`;
    182             }
    183             let reports;
    184             if (properties.reports_total) {
    185                 reports =
    186                     `<br>Отчетов: ${properties.reports_total}, ` +
    187                     `с фото: ${properties.reports_photo || 0}, ` +
    188                     `с описанием: ${properties.reports_tech || 0}`;
    189             } else {
    190                 reports = '<br>Отчетов нет';
    191             }
    192             const region = properties.regions.map((regionId) => {
    193                 const name = escapeHtml(this.regions[regionId].name);
    194                 const id = escapeHtml(regionId);
    195                 return `<a href="${regionUrlBase}/${id}">${name}</a>`;
    196             }).join(' / ');
    197 
    198             let description = `
    199                 <table class="pass-details">
    200                     <tr>
    201                         <td>${properties.is_summit ? 'Вершина ' : 'Перевал '}</td>
    202                         <td>${properties.name ? escapeHtml(properties.name) : 'название неизвестно'}</td>
    203                     </tr>
    204                     ${altnames}
    205                     <tr>
    206                         <td>Категория</td>
    207                         <td>${properties.grade ? escapeHtml(properties.grade) : "неизвестная"}</td>
    208                     </tr>
    209                     <tr>
    210                         <td>Высота</td>
    211                         <td>${properties.elevation ? (escapeHtml(properties.elevation) + ' м') : 'неизвестная'}</td>
    212                     </tr>
    213                     ${connects}
    214                     <tr>
    215                         <td>Характеристика склонов</td>
    216                         <td>${properties.slopes ? escapeHtml(properties.slopes) : "неизвестная"}</td>
    217                     </tr>
    218                     <tr>
    219                         <td>Координаты</td>
    220                         <td>
    221                             <table class="coords">
    222                                 <tr class="header">
    223                                     <td>Широта</td>
    224                                     <td>Долгота</td>
    225                                 </tr>
    226                                 <tr>
    227                                     <td>${latLng.lat.toFixed(5)}</td>
    228                                     <td>${latLng.lng.toFixed(5)}</td>
    229                                     <td><a id="westra-pass-gpx" title="Сохранить">gpx</a></td>
    230                                     <td><a id="westra-pass-kml" title="Сохранить">kml</a></td>
    231                                 </tr>
    232                             </table>
    233                         </td>
    234                     </tr>
    235                     <tr>
    236                         <td>На сайте Вестры</td>
    237                         <td><a id="westra-pass-link" href="${passUrl}">${passUrl}</a>${reports}</td></tr>
    238                     <tr>
    239                         <td>Добавил</td>
    240                         <td>${properties.author ? escapeHtml(properties.author) : "неизвестно"}</td>
    241                     </tr>
    242                     ${comments}
    243                     <tr>
    244                         <td>Район</td>
    245                         <td>${region}</td>
    246                     </tr>
    247 
    248                 </table>`;
    249             this._map.openPopup(description, latLng, {maxWidth: 500});
    250             document.getElementById('westra-pass-link').onclick = function() {
    251                 openPopupWindow(passUrl, 780, 'westra-details');
    252                 return false;
    253             };
    254             document.getElementById('westra-pass-gpx').onclick = function() {
    255                 this._passToGpx(e.marker);
    256                 return false;
    257             }.bind(this);
    258             document.getElementById('westra-pass-kml').onclick = function() {
    259                 this._passToKml(e.marker);
    260                 return false;
    261             }.bind(this);
    262         }
    263     }
    264 );
    265 
    266 export {WestraPassesMarkers};