westraPassesMarkers.js (10564B)
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_passes.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: function() { 25 if (this._downloadStarted) { 26 return; 27 } 28 this._downloadStarted = true; 29 fetch(this.url) 30 .then( 31 (xhr) => this._loadMarkers(xhr), 32 (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 }, 39 40 onAdd: function(map) { 41 L.Layer.CanvasMarkers.prototype.onAdd.call(this, map); 42 this.loadData(); 43 }, 44 45 _makeTooltip: function(marker) { 46 var properties = marker.properties, 47 toolTip = properties.grade || ''; 48 if (toolTip && properties.elevation) { 49 toolTip += ', '; 50 } 51 toolTip += properties.elevation || ''; 52 if (toolTip) { 53 toolTip = ' (' + toolTip + ')'; 54 } 55 toolTip = (properties.name || 'без названия') + toolTip; 56 toolTip = (properties.is_summit ? 'Вершина ' : 'Перевал ') + toolTip; 57 return toolTip; 58 }, 59 60 _passToGpx: function(marker) { 61 let label = marker.tooltip; 62 if (typeof label === 'function') { 63 label = label(marker); 64 } 65 label = escapeHtml(label); 66 const gpx = `<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 67 <gpx xmlns="http://www.topografix.com/GPX/1/1" 68 creator="http://nakarte.me" 69 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 70 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" 71 version="1.1"> 72 <wpt lat="${marker.latlng.lat.toFixed(6)}" lon="${marker.latlng.lng.toFixed(6)}"> 73 <name>${label}</name> 74 </wpt> 75 </gpx> 76 `; 77 var filename = marker.properties.name || 'Без названия'; 78 saveAs(new Blob([gpx], {type: 'application/gpx+xml'}), filename + '.gpx', true); 79 }, 80 81 _passToKml: function(marker) { 82 let label = marker.tooltip; 83 if (typeof label === 'function') { 84 label = label(marker); 85 } 86 label = escapeHtml(label); 87 const kml = `<?xml version="1.0" encoding="UTF-8"?> 88 <kml xmlns="http://www.opengis.net/kml/2.2"> 89 <Placemark> 90 <name>${label}</name> 91 <Point> 92 <coordinates> 93 ${marker.latlng.lng.toFixed(6)},${marker.latlng.lat.toFixed(6)},0 94 </coordinates> 95 </Point> 96 </Placemark> 97 </kml> 98 `; 99 var filename = marker.properties.name || 'Без названия'; 100 saveAs(new Blob([kml], {type: 'application/vnd.google-earth.kml+xml'}), filename + '.kml', true); 101 }, 102 103 _makeIcon: function(marker) { 104 var className; 105 className = 'westra-pass-marker '; 106 if (marker.properties.is_summit) { 107 className += 'westra-pass-marker-summit'; 108 } else { 109 className += 'westra-pass-marker-' + marker.properties.grade_eng; 110 } 111 return iconFromBackgroundImage(className); 112 }, 113 114 _loadMarkers: function(xhr) { 115 var markers = [], 116 features = JSON.parse(xhr.response), 117 feature, i, marker; 118 for (i = 0; i < features.length; i++) { 119 feature = features[i]; 120 marker = { 121 latlng: { 122 lat: feature.latlon[0], 123 lng: feature.latlon[1] 124 }, 125 label: feature.name || "", 126 icon: this._makeIcon, 127 tooltip: this._makeTooltip.bind(this), 128 properties: feature 129 }; 130 markers.push(marker); 131 } 132 this.addMarkers(markers); 133 this._dataLoaded = true; 134 this.fire('data-loaded'); 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 url = 'https://westra.ru/passes/Passes/' + properties.id; 144 let altnames = '', 145 connects = '', 146 comments = ''; 147 if (properties.altnames) { 148 altnames = ` 149 <tr> 150 <td>Другие названия</td> 151 <td>${escapeHtml(properties.altnames)}</td> 152 </tr>`; 153 } 154 155 if (!properties.is_summit) { 156 connects = ` 157 <tr> 158 <td>Соединяет</td> 159 <td>${properties.connects ? escapeHtml(properties.connects) : "неизвестнo"}</td> 160 </tr>`; 161 } 162 163 if (properties.comments) { 164 for (let comment of properties.comments) { 165 let user = ''; 166 if (comment.user) { 167 user = ( 168 `<span class="westra-passes-description-comment-author">${escapeHtml(comment.user)}:</span>` 169 ); 170 } 171 comments += ( 172 `<p class="westra-passes-description-comment">${user}${escapeHtml(comment.content)}</p>` 173 ); 174 } 175 comments = ` 176 <tr> 177 <td>Комментарии</td> 178 <td>${comments}</td> 179 </tr>`; 180 } 181 let reports; 182 if (properties.reports_total) { 183 reports = 184 `<br>Отчетов: ${properties.reports_total}, ` + 185 `с фото: ${properties.reports_photo || 0}, ` + 186 `с описанием: ${properties.reports_tech || 0}`; 187 } else { 188 reports = '<br>Отчетов нет'; 189 } 190 let description = ` 191 <table class="pass-details"> 192 <tr> 193 <td>${properties.is_summit ? 'Вершина ' : 'Перевал '}</td> 194 <td>${properties.name ? escapeHtml(properties.name) : 'название неизвестно'}</td> 195 </tr> 196 ${altnames} 197 <tr> 198 <td>Категория</td> 199 <td>${properties.grade ? escapeHtml(properties.grade) : "неизвестная"}</td> 200 </tr> 201 <tr> 202 <td>Высота</td> 203 <td>${properties.elevation ? (escapeHtml(properties.elevation) + ' м') : 'неизвестная'}</td> 204 </tr> 205 ${connects} 206 <tr> 207 <td>Характеристика склонов</td> 208 <td>${properties.slopes ? escapeHtml(properties.slopes) : "неизвестная"}</td> 209 </tr> 210 <tr> 211 <td>Координаты</td> 212 <td> 213 <table class="coords"> 214 <tr class="header"> 215 <td>Широта</td> 216 <td>Долгота</td> 217 </tr> 218 <tr> 219 <td>${latLng.lat.toFixed(5)}</td> 220 <td>${latLng.lng.toFixed(5)}</td> 221 <td><a id="westra-pass-gpx" title="Сохранить">gpx</a></td> 222 <td><a id="westra-pass-kml" title="Сохранить">kml</a></td> 223 </tr> 224 </table> 225 </td> 226 </tr> 227 <tr> 228 <td>На сайте Вестры</td> 229 <td><a id="westra-pass-link" href="${url}">${url}</a>${reports}</td></tr> 230 <tr> 231 <td>Добавил</td> 232 <td>${properties.author ? escapeHtml(properties.author) : "неизвестно"}</td> 233 </tr> 234 ${comments} 235 </table>`; 236 this._map.openPopup(description, latLng, {maxWidth: 500}); 237 document.getElementById('westra-pass-link').onclick = function() { 238 openPopupWindow(url, 780, 'westra-details'); 239 return false; 240 }; 241 document.getElementById('westra-pass-gpx').onclick = function() { 242 this._passToGpx(e.marker); 243 return false; 244 }.bind(this); 245 document.getElementById('westra-pass-kml').onclick = function() { 246 this._passToKml(e.marker); 247 return false; 248 }.bind(this); 249 } 250 } 251 ); 252 253 export {WestraPassesMarkers};