2020-06-05 00:22:41 +02:00
|
|
|
'use strict';
|
|
|
|
|
2020-06-01 21:13:02 +02:00
|
|
|
(function () {
|
|
|
|
var MapEditor = {
|
|
|
|
map: null,
|
|
|
|
panorama: null,
|
|
|
|
selectedMarker: null,
|
2020-06-05 00:22:41 +02:00
|
|
|
added: {},
|
|
|
|
edited: {},
|
|
|
|
deleted: {},
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-03 23:41:08 +02:00
|
|
|
getPlace: function (placeId, marker) {
|
2020-06-02 21:44:01 +02:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'json';
|
|
|
|
xhr.onload = function () {
|
|
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
|
|
|
|
if (!this.response.panoId) {
|
|
|
|
document.getElementById('noPano').style.visibility = 'visible';
|
2020-06-03 23:41:08 +02:00
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
places[marker.placeId].panoId = -1;
|
|
|
|
places[marker.placeId].noPano = true;
|
2020-06-03 23:41:08 +02:00
|
|
|
|
2020-06-02 21:44:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
places[marker.placeId].panoId = this.response.panoId;
|
|
|
|
places[marker.placeId].noPano = false;
|
|
|
|
|
|
|
|
MapEditor.loadPano(this.response.panoId, places[marker.placeId].pov);
|
2020-06-02 21:44:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
xhr.open('GET', '/admin/place.json/' + placeId, true);
|
|
|
|
xhr.send();
|
|
|
|
},
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
loadPano: function (panoId, pov) {
|
2020-06-01 21:13:02 +02:00
|
|
|
MapEditor.panorama.setVisible(true);
|
2020-06-05 00:22:41 +02:00
|
|
|
MapEditor.panorama.setPov({ heading: pov.heading, pitch: pov.pitch });
|
|
|
|
MapEditor.panorama.setZoom(pov.zoom);
|
2020-06-02 21:44:01 +02:00
|
|
|
MapEditor.panorama.setPano(panoId);
|
2020-06-01 21:13:02 +02:00
|
|
|
},
|
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
loadPanoForNewPlace: function (panoLocationData) {
|
2020-06-05 00:22:41 +02:00
|
|
|
var placeId = MapEditor.selectedMarker.placeId;
|
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
if (!panoLocationData) {
|
2020-06-05 00:22:41 +02:00
|
|
|
places[placeId].panoId = -1;
|
|
|
|
places[placeId].noPano = true;
|
2020-06-04 19:30:35 +02:00
|
|
|
|
|
|
|
document.getElementById('noPano').style.visibility = 'visible';
|
2020-06-05 00:22:41 +02:00
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
var latLng = panoLocationData.latLng;
|
|
|
|
|
|
|
|
places[placeId].panoId = panoLocationData.pano;
|
|
|
|
places[placeId].lat = latLng.lat();
|
|
|
|
places[placeId].lng = latLng.lng();
|
|
|
|
|
|
|
|
MapEditor.selectedMarker.setLatLng({ lat: places[placeId].lat, lng: places[placeId].lng });
|
|
|
|
MapEditor.map.panTo(MapEditor.selectedMarker.getLatLng());
|
2020-06-04 19:30:35 +02:00
|
|
|
|
|
|
|
MapEditor.panorama.setVisible(true);
|
2020-06-05 00:22:41 +02:00
|
|
|
MapEditor.panorama.setPov({ heading: 0.0, pitch: 0.0 });
|
|
|
|
MapEditor.panorama.setZoom(0.0);
|
2020-06-04 19:30:35 +02:00
|
|
|
MapEditor.panorama.setPano(panoLocationData.pano);
|
|
|
|
},
|
|
|
|
|
|
|
|
requestPanoData: function (location, canBeIndoor) {
|
|
|
|
var sv = new google.maps.StreetViewService();
|
|
|
|
|
|
|
|
sv.getPanorama({
|
|
|
|
location: location,
|
|
|
|
preference: google.maps.StreetViewPreference.NEAREST,
|
2020-06-05 00:22:41 +02:00
|
|
|
radius: 100,
|
2020-06-04 19:30:35 +02:00
|
|
|
source: canBeIndoor ? google.maps.StreetViewSource.DEFAULT : google.maps.StreetViewSource.OUTDOOR
|
|
|
|
}, function (data, status) {
|
|
|
|
var panoLocationData = status === google.maps.StreetViewStatus.OK ? data.location : null;
|
|
|
|
|
|
|
|
if (panoLocationData === null && !canBeIndoor) {
|
|
|
|
MapEditor.requestPanoData(location, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
document.getElementById('loading').style.visibility = 'hidden';
|
|
|
|
|
|
|
|
MapEditor.loadPanoForNewPlace(panoLocationData);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2020-06-01 21:13:02 +02:00
|
|
|
select: function (marker) {
|
2020-06-05 00:22:41 +02:00
|
|
|
if (MapEditor.selectedMarker === marker) {
|
|
|
|
return;
|
|
|
|
}
|
2020-06-01 21:13:02 +02:00
|
|
|
|
|
|
|
document.getElementById('map').classList.add('selected');
|
2020-06-02 21:49:37 +02:00
|
|
|
document.getElementById('control').classList.add('selected');
|
2020-06-01 21:13:02 +02:00
|
|
|
document.getElementById('noPano').style.visibility = 'hidden';
|
2020-06-02 21:49:37 +02:00
|
|
|
document.getElementById('panorama').style.visibility = 'visible';
|
2020-06-01 21:13:02 +02:00
|
|
|
document.getElementById('placeControl').style.visibility = 'visible';
|
|
|
|
|
|
|
|
MapEditor.resetSelected();
|
|
|
|
MapEditor.selectedMarker = marker;
|
|
|
|
|
|
|
|
MapEditor.map.invalidateSize(true);
|
|
|
|
MapEditor.map.panTo(marker.getLatLng());
|
|
|
|
|
|
|
|
MapEditor.panorama.setVisible(false);
|
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
if (marker.placeId) {
|
2020-06-05 00:22:41 +02:00
|
|
|
marker.setIcon(IconCollection.iconBlue);
|
|
|
|
marker.setZIndexOffset(2000);
|
|
|
|
|
|
|
|
document.getElementById('deleteButton').style.display = 'block';
|
|
|
|
|
|
|
|
if (places[marker.placeId].panoId) {
|
|
|
|
if (places[marker.placeId].panoId === -1) {
|
|
|
|
document.getElementById('noPano').style.visibility = 'visible';
|
|
|
|
} else {
|
|
|
|
MapEditor.loadPano(places[marker.placeId].panoId, places[marker.placeId].pov);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
MapEditor.getPlace(marker.placeId, marker);
|
|
|
|
} else {
|
2020-06-05 00:22:41 +02:00
|
|
|
marker.placeId = 'new_' + new Date().getTime();
|
|
|
|
|
|
|
|
var latLng = marker.getLatLng();
|
|
|
|
|
|
|
|
places[marker.placeId] = { id: null, lat: latLng.lat, lng: latLng.lng, panoId: null, pov: { heading: 0.0, pitch: 0.0, zoom: 0 }, noPano: false };
|
|
|
|
|
|
|
|
document.getElementById('loading').style.visibility = 'visible';
|
|
|
|
|
|
|
|
MapEditor.requestPanoData(latLng);
|
2020-06-04 19:30:35 +02:00
|
|
|
}
|
2020-06-01 21:13:02 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
resetSelected: function () {
|
|
|
|
if (!MapEditor.selectedMarker) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
var placeId = MapEditor.selectedMarker.placeId
|
|
|
|
|
|
|
|
if (places[placeId].id) {
|
|
|
|
MapEditor.selectedMarker.setIcon(places[placeId].noPano ? IconCollection.iconRed : IconCollection.iconGreen);
|
2020-06-04 19:30:35 +02:00
|
|
|
MapEditor.selectedMarker.setZIndexOffset(1000);
|
|
|
|
} else {
|
2020-06-05 00:22:41 +02:00
|
|
|
delete places[placeId];
|
2020-06-04 19:30:35 +02:00
|
|
|
MapEditor.map.removeLayer(MapEditor.selectedMarker);
|
|
|
|
}
|
2020-06-05 00:22:41 +02:00
|
|
|
|
|
|
|
document.getElementById('deleteButton').style.display = 'none';
|
|
|
|
},
|
|
|
|
|
|
|
|
applyPlace: function () {
|
|
|
|
var placeId = MapEditor.selectedMarker.placeId;
|
|
|
|
|
|
|
|
if (!places[placeId].noPano) {
|
|
|
|
var latLng = MapEditor.panorama.getPosition();
|
|
|
|
var pov = MapEditor.panorama.getPov();
|
|
|
|
var zoom = MapEditor.panorama.getZoom();
|
|
|
|
|
|
|
|
places[placeId].lat = latLng.lat();
|
|
|
|
places[placeId].lng = latLng.lng();
|
|
|
|
places[placeId].panoId = MapEditor.panorama.getPano();
|
|
|
|
places[placeId].pov = { heading: pov.heading, pitch: pov.pitch, zoom: zoom };
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!places[placeId].id) {
|
|
|
|
places[placeId].id = 'new';
|
|
|
|
MapEditor.added[placeId] = places[placeId];
|
|
|
|
|
|
|
|
document.getElementById('deleteButton').style.display = 'block';
|
|
|
|
} else {
|
|
|
|
MapEditor.edited[placeId] = places[placeId];
|
|
|
|
}
|
|
|
|
|
|
|
|
MapEditor.selectedMarker.setLatLng({ lat: places[placeId].lat, lng: places[placeId].lng });
|
|
|
|
},
|
|
|
|
|
|
|
|
closePlace: function () {
|
|
|
|
document.getElementById('map').classList.remove('selected');
|
|
|
|
document.getElementById('control').classList.remove('selected');
|
|
|
|
document.getElementById('noPano').style.visibility = 'hidden';
|
|
|
|
document.getElementById('panorama').style.visibility = 'hidden';
|
|
|
|
document.getElementById('placeControl').style.visibility = 'hidden';
|
|
|
|
|
|
|
|
MapEditor.resetSelected();
|
|
|
|
MapEditor.selectedMarker = null;
|
|
|
|
|
|
|
|
MapEditor.map.invalidateSize(true);
|
|
|
|
},
|
|
|
|
|
|
|
|
deletePlace: function () {
|
|
|
|
document.getElementById('map').classList.remove('selected');
|
|
|
|
document.getElementById('control').classList.remove('selected');
|
|
|
|
document.getElementById('noPano').style.visibility = 'hidden';
|
|
|
|
document.getElementById('panorama').style.visibility = 'hidden';
|
|
|
|
document.getElementById('placeControl').style.visibility = 'hidden';
|
|
|
|
document.getElementById('deleteButton').style.display = 'none';
|
|
|
|
|
|
|
|
var placeId = MapEditor.selectedMarker.placeId;
|
|
|
|
|
|
|
|
if (places[placeId].id && !MapEditor.added[placeId]) {
|
|
|
|
MapEditor.deleted[placeId] = places[placeId];
|
|
|
|
}
|
|
|
|
|
|
|
|
delete places[placeId];
|
|
|
|
delete MapEditor.added[placeId];
|
|
|
|
delete MapEditor.edited[placeId];
|
|
|
|
|
|
|
|
MapEditor.map.removeLayer(MapEditor.selectedMarker);
|
|
|
|
MapEditor.selectedMarker = null;
|
|
|
|
|
|
|
|
MapEditor.map.invalidateSize(true);
|
2020-06-01 21:13:02 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-03 23:41:08 +02:00
|
|
|
var IconCollection = {
|
|
|
|
iconGreen: L.icon({
|
|
|
|
iconUrl: '/static/img/markers/marker-green.svg',
|
|
|
|
iconSize: [24, 32],
|
|
|
|
iconAnchor: [12, 32]
|
|
|
|
}),
|
|
|
|
iconRed: L.icon({
|
|
|
|
iconUrl: '/static/img/markers/marker-red.svg',
|
|
|
|
iconSize: [24, 32],
|
|
|
|
iconAnchor: [12, 32]
|
|
|
|
}),
|
|
|
|
iconBlue: L.icon({
|
|
|
|
iconUrl: '/static/img/markers/marker-blue.svg',
|
|
|
|
iconSize: [24, 32],
|
|
|
|
iconAnchor: [12, 32]
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2020-06-02 21:51:25 +02:00
|
|
|
var Util = {
|
|
|
|
getHighResData: function () {
|
|
|
|
if (window.devicePixelRatio >= 4) {
|
|
|
|
return { ppi: 320, tileSize: 128, zoomOffset: 1 };
|
|
|
|
} else if (window.devicePixelRatio >= 2) {
|
|
|
|
return { ppi: 250, tileSize: 256, zoomOffset: 0 };
|
|
|
|
} else {
|
|
|
|
return { ppi: 72, tileSize: 512, zoomOffset: -1 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-01 21:13:02 +02:00
|
|
|
MapEditor.map = L.map('map', {
|
|
|
|
attributionControl: false,
|
|
|
|
zoomControl: false
|
|
|
|
});
|
|
|
|
|
2020-06-04 19:30:35 +02:00
|
|
|
MapEditor.map.on('click', function (e) {
|
|
|
|
var marker = L.marker(e.latlng, {
|
|
|
|
icon: IconCollection.iconBlue,
|
2020-06-05 00:22:41 +02:00
|
|
|
zIndexOffset: 2000
|
2020-06-04 19:30:35 +02:00
|
|
|
})
|
2020-06-05 00:22:41 +02:00
|
|
|
.addTo(MapEditor.map)
|
|
|
|
.on('click', function () {
|
|
|
|
MapEditor.select(this);
|
|
|
|
});
|
2020-06-04 19:30:35 +02:00
|
|
|
|
|
|
|
MapEditor.select(marker);
|
|
|
|
});
|
|
|
|
|
2020-06-02 21:51:25 +02:00
|
|
|
var highResData = Util.getHighResData();
|
|
|
|
|
2020-06-01 21:13:02 +02:00
|
|
|
L.tileLayer(tileUrl, {
|
2020-06-02 21:51:25 +02:00
|
|
|
subdomains: '1234',
|
|
|
|
ppi: highResData.ppi,
|
|
|
|
tileSize: highResData.tileSize,
|
|
|
|
zoomOffset: highResData.zoomOffset,
|
2020-06-01 21:13:02 +02:00
|
|
|
minZoom: 0,
|
|
|
|
maxZoom: 20
|
|
|
|
}).addTo(MapEditor.map);
|
|
|
|
|
|
|
|
MapEditor.map.fitBounds(L.latLngBounds({ lat: mapBounds.south, lng: mapBounds.west }, { lat: mapBounds.north, lng: mapBounds.east }));
|
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
for (var placeId in places) {
|
|
|
|
if (!places.hasOwnProperty(placeId)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
var place = places[placeId];
|
|
|
|
|
|
|
|
var marker = L.marker({ lat: place.lat, lng: place.lng }, {
|
|
|
|
icon: place.noPano ? IconCollection.iconRed : IconCollection.iconGreen,
|
2020-06-01 21:13:02 +02:00
|
|
|
zIndexOffset: 1000
|
|
|
|
})
|
|
|
|
.addTo(MapEditor.map)
|
|
|
|
.on('click', function () {
|
|
|
|
MapEditor.select(this);
|
|
|
|
});
|
2020-06-02 21:44:01 +02:00
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
marker.placeId = place.id;
|
2020-06-01 21:13:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
|
|
|
|
// switch off fullscreenControl because positioning doesn't work
|
|
|
|
fullscreenControl: false,
|
|
|
|
fullscreenControlOptions: {
|
|
|
|
position: google.maps.ControlPosition.LEFT_TOP
|
2020-06-01 22:07:13 +02:00
|
|
|
},
|
|
|
|
motionTracking: false
|
2020-06-01 21:13:02 +02:00
|
|
|
});
|
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
document.getElementById('applyButton').onclick = function () {
|
|
|
|
MapEditor.applyPlace();
|
|
|
|
};
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
document.getElementById('cancelButton').onclick = function () {
|
|
|
|
MapEditor.closePlace();
|
|
|
|
};
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-05 00:22:41 +02:00
|
|
|
document.getElementById('deleteButton').onclick = function () {
|
|
|
|
MapEditor.deletePlace();
|
2020-06-01 21:13:02 +02:00
|
|
|
};
|
|
|
|
})();
|