[TASK] Move polyfills and test properties

This commit is contained in:
Xaver Maierhofer 2017-04-30 14:59:39 +02:00
parent ebc3ca4804
commit bd7a93de73
No known key found for this signature in database
GPG Key ID: 7FDCE23FD2EC9FE8
5 changed files with 334 additions and 328 deletions

View File

@ -16,5 +16,37 @@
"fr", "fr",
"ru" "ru"
], ],
"icon": {
"base": {
"fillOpacity": 0.6,
"opacity": 0.6,
"weight": 2,
"radius": 6,
"className": "stroke-first"
},
"online": {
"color": "#1566A9",
"fillColor": "#1566A9"
},
"offline": {
"color": "#D43E2A",
"fillColor": "#D43E2A",
"radius": 3
},
"lost": {
"color": "#D43E2A",
"fillColor": "#D43E2A",
"radius": 4
},
"alert": {
"color": "#D43E2A",
"fillColor": "#D43E2A",
"radius": 5
},
"new": {
"color": "#1566A9",
"fillColor": "#93E929"
}
},
"cacheBreaker": "<!-- inject:cache-breaker -->" "cacheBreaker": "<!-- inject:cache-breaker -->"
} }

View File

@ -1,5 +1,5 @@
define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationmarker', 'rbush', 'helper'], define(['map/clientlayer', 'map/labellayer', 'map/button', 'leaflet'],
function (ClientLayer, LabelLayer, L, moment, LocationMarker, rbush, helper) { function (ClientLayer, LabelLayer, Button, L) {
'use strict'; 'use strict';
var options = { var options = {
@ -8,197 +8,14 @@ define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationm
minZoom: 0 minZoom: 0
}; };
var ButtonBase = L.Control.extend({
options: {
position: 'bottomright'
},
active: false,
button: undefined,
initialize: function (f, o) {
L.Util.setOptions(this, o);
this.f = f;
},
update: function () {
this.button.classList.toggle('active', this.active);
},
set: function (v) {
this.active = v;
this.update();
}
});
var LocateButton = ButtonBase.extend({
onAdd: function () {
var button = L.DomUtil.create('button', 'ion-locate shadow');
button.setAttribute('data-tooltip', _.t('button.tracking'));
L.DomEvent.disableClickPropagation(button);
L.DomEvent.addListener(button, 'click', this.onClick, this);
this.button = button;
return button;
},
onClick: function () {
this.f(!this.active);
}
});
var CoordsPickerButton = ButtonBase.extend({
onAdd: function () {
var button = L.DomUtil.create('button', 'ion-pin shadow');
button.setAttribute('data-tooltip', _.t('button.location'));
// Click propagation isn't disabled as this causes problems with the
// location picking mode; instead propagation is stopped in onClick().
L.DomEvent.addListener(button, 'click', this.onClick, this);
this.button = button;
return button;
},
onClick: function (e) {
L.DomEvent.stopPropagation(e);
this.f(!this.active);
}
});
function mkMarker(dict, iconFunc, router) {
return function (d) {
var m = L.circleMarker([d.nodeinfo.location.latitude, d.nodeinfo.location.longitude], iconFunc(d));
m.resetStyle = function resetStyle() {
m.setStyle(iconFunc(d));
};
m.on('click', function () {
router.fullUrl({ node: d.nodeinfo.node_id });
});
m.bindTooltip(d.nodeinfo.hostname);
dict[d.nodeinfo.node_id] = m;
return m;
};
}
function addLinksToMap(dict, linkScale, graph, router) {
graph = graph.filter(function (d) {
return 'distance' in d && !d.vpn;
});
return graph.map(function (d) {
var opts = {
color: linkScale(1 / d.tq),
weight: 4,
opacity: 0.5,
dashArray: 'none'
};
var line = L.polyline(d.latlngs, opts);
line.resetStyle = function resetStyle() {
line.setStyle(opts);
};
line.bindTooltip(d.source.node.nodeinfo.hostname + ' ' + d.target.node.nodeinfo.hostname + '<br><strong>' + helper.showDistance(d) + ' / ' + helper.showTq(d) + '</strong>');
line.on('click', function () {
router.fullUrl({ link: d.id });
});
dict[d.id] = line;
return line;
});
}
var iconOnline = {
color: '#1566A9',
fillColor: '#1566A9',
radius: 6,
fillOpacity: 0.5,
opacity: 0.5,
weight: 2,
className: 'stroke-first'
};
var iconOffline = {
color: '#D43E2A',
fillColor: '#D43E2A',
radius: 3,
fillOpacity: 0.5,
opacity: 0.5,
weight: 1,
className: 'stroke-first'
};
var iconLost = {
color: '#D43E2A',
fillColor: '#D43E2A',
radius: 4,
fillOpacity: 0.8,
opacity: 0.8,
weight: 1,
className: 'stroke-first'
};
var iconAlert = {
color: '#D43E2A',
fillColor: '#D43E2A',
radius: 5,
fillOpacity: 0.8,
opacity: 0.8,
weight: 2,
className: 'stroke-first'
};
var iconNew = { color: '#1566A9', fillColor: '#93E929', radius: 6, fillOpacity: 1.0, opacity: 0.5, weight: 2 };
return function (config, linkScale, sidebar, router, buttons) { return function (config, linkScale, sidebar, router, buttons) {
var self = this; var self = this;
var groupOnline;
var groupOffline;
var groupNew;
var groupLost;
var groupLines;
var savedView; var savedView;
var map; var map;
var userLocation;
var layerControl; var layerControl;
var baseLayers = {}; var baseLayers = {};
var locateUserButton = new LocateButton(function (d) {
if (d) {
enableTracking();
} else {
disableTracking();
}
});
var mybuttons = [];
function addButton(button) {
var el = button.onAdd();
mybuttons.push(el);
buttons.appendChild(el);
}
function clearButtons() {
mybuttons.forEach(function (d) {
buttons.removeChild(d);
});
}
var showCoordsPickerButton = new CoordsPickerButton(function (d) {
if (d) {
enableCoords();
} else {
disableCoords();
}
});
function saveView() { function saveView() {
savedView = { savedView = {
center: map.getCenter(), center: map.getCenter(),
@ -206,54 +23,6 @@ define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationm
}; };
} }
function enableTracking() {
map.locate({
watch: true,
enableHighAccuracy: true,
setView: true
});
locateUserButton.set(true);
}
function disableTracking() {
map.stopLocate();
locationError();
locateUserButton.set(false);
}
function enableCoords() {
map.getContainer().classList.add('pick-coordinates');
map.on('click', showCoordinates);
showCoordsPickerButton.set(true);
}
function disableCoords() {
map.getContainer().classList.remove('pick-coordinates');
map.off('click', showCoordinates);
showCoordsPickerButton.set(false);
}
function showCoordinates(e) {
router.fullUrl({ zoom: map.getZoom(), lat: e.latlng.lat, lng: e.latlng.lng });
disableCoords();
}
function locationFound(e) {
if (!userLocation) {
userLocation = new LocationMarker(e.latlng).addTo(map);
}
userLocation.setLatLng(e.latlng);
userLocation.setAccuracy(e.accuracy);
}
function locationError() {
if (userLocation) {
map.removeLayer(userLocation);
userLocation = null;
}
}
function contextMenuOpenLayerMenu() { function contextMenuOpenLayerMenu() {
document.querySelector('.leaflet-control-layers').classList.add('leaflet-control-layers-expanded'); document.querySelector('.leaflet-control-layers').classList.add('leaflet-control-layers-expanded');
} }
@ -288,13 +57,14 @@ define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationm
baseLayers[d.name] = d.layer; baseLayers[d.name] = d.layer;
}); });
map.on('locationfound', locationFound); var button = new Button(config, map, router, buttons);
map.on('locationerror', locationError);
map.on('locationfound', button.locationFound);
map.on('locationerror', button.locationError);
map.on('dragend', saveView); map.on('dragend', saveView);
map.on('contextmenu', contextMenuOpenLayerMenu); map.on('contextmenu', contextMenuOpenLayerMenu);
addButton(locateUserButton); button.init();
addButton(showCoordsPickerButton);
layerControl = L.control.layers(baseLayers, [], { position: 'bottomright' }); layerControl = L.control.layers(baseLayers, [], { position: 'bottomright' });
layerControl.addTo(map); layerControl.addTo(map);
@ -392,116 +162,41 @@ define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationm
} }
} }
function mapRTree(d) {
return {
minX: d.nodeinfo.location.latitude, minY: d.nodeinfo.location.longitude,
maxX: d.nodeinfo.location.latitude, maxY: d.nodeinfo.location.longitude,
node: d
};
}
self.setData = function setData(data) { self.setData = function setData(data) {
nodeDict = {}; nodeDict = {};
linkDict = {}; linkDict = {};
if (groupOffline) { clientLayer.setData(data);
groupOffline.clearLayers(); labelLayer.setData(data, map, nodeDict, linkDict, linkScale, router, config);
}
if (groupOnline) {
groupOnline.clearLayers();
}
if (groupNew) {
groupNew.clearLayers();
}
if (groupLost) {
groupLost.clearLayers();
}
if (groupLines) {
groupLines.clearLayers();
}
var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router);
groupLines = L.featureGroup(lines).addTo(map);
var nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new);
var nodesOffline = helper.subtract(data.nodes.all.filter(helper.offline), data.nodes.lost);
var markersOnline = nodesOnline.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconOnline;
}, router));
var markersOffline = nodesOffline.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconOffline;
}, router));
var markersNew = data.nodes.new.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconNew;
}, router));
var markersLost = data.nodes.lost.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function (d) {
if (d.lastseen.isAfter(moment(data.now).subtract(config.maxAgeAlert, 'days'))) {
return iconAlert;
}
if (d.lastseen.isAfter(moment(data.now).subtract(config.maxAge, 'days'))) {
return iconLost;
}
return null;
}, router));
groupOffline = L.featureGroup(markersOffline).addTo(map);
groupLost = L.featureGroup(markersLost).addTo(map);
groupOnline = L.featureGroup(markersOnline).addTo(map);
groupNew = L.featureGroup(markersNew).addTo(map);
var rtreeOnlineAll = rbush(9);
rtreeOnlineAll.load(data.nodes.all.filter(helper.online).filter(helper.hasLocation).map(mapRTree));
clientLayer.setData(rtreeOnlineAll);
labelLayer.setData({
online: nodesOnline.filter(helper.hasLocation),
offline: nodesOffline.filter(helper.hasLocation),
new: data.nodes.new.filter(helper.hasLocation),
lost: data.nodes.lost.filter(helper.hasLocation)
});
updateView(true); updateView(true);
}; };
self.resetView = function resetView() { self.resetView = function resetView() {
disableTracking(); button.disableTracking();
highlight = undefined; highlight = undefined;
updateView(); updateView();
}; };
self.gotoNode = function gotoNode(d) { self.gotoNode = function gotoNode(d) {
disableTracking(); button.disableTracking();
highlight = { type: 'node', o: d }; highlight = { type: 'node', o: d };
updateView(); updateView();
}; };
self.gotoLink = function gotoLink(d) { self.gotoLink = function gotoLink(d) {
disableTracking(); button.disableTracking();
highlight = { type: 'link', o: d }; highlight = { type: 'link', o: d };
updateView(); updateView();
}; };
self.gotoLocation = function gotoLocation(d) { self.gotoLocation = function gotoLocation(d) {
disableTracking(); button.disableTracking();
map.setView([d.lat, d.lng], d.zoom); map.setView([d.lat, d.lng], d.zoom);
}; };
self.destroy = function destroy() { self.destroy = function destroy() {
clearButtons(); button.clearButtons();
map.remove(); map.remove();
if (el.parentNode) { if (el.parentNode) {

154
lib/map/button.js Normal file
View File

@ -0,0 +1,154 @@
define(['map/clientlayer', 'map/labellayer', 'leaflet', 'moment', 'map/locationmarker'],
function (ClientLayer, LabelLayer, L, moment, LocationMarker) {
'use strict';
var self = {};
var ButtonBase = L.Control.extend({
options: {
position: 'bottomright'
},
active: false,
button: undefined,
initialize: function (f, o) {
L.Util.setOptions(this, o);
this.f = f;
},
update: function () {
this.button.classList.toggle('active', this.active);
},
set: function (v) {
this.active = v;
this.update();
}
});
var LocateButton = ButtonBase.extend({
onAdd: function () {
var button = L.DomUtil.create('button', 'ion-locate shadow');
button.setAttribute('data-tooltip', _.t('button.tracking'));
L.DomEvent.disableClickPropagation(button);
L.DomEvent.addListener(button, 'click', this.onClick, this);
this.button = button;
return button;
},
onClick: function () {
this.f(!this.active);
}
});
var CoordsPickerButton = ButtonBase.extend({
onAdd: function () {
var button = L.DomUtil.create('button', 'ion-pin shadow');
button.setAttribute('data-tooltip', _.t('button.location'));
// Click propagation isn't disabled as this causes problems with the
// location picking mode; instead propagation is stopped in onClick().
L.DomEvent.addListener(button, 'click', this.onClick, this);
this.button = button;
return button;
},
onClick: function (e) {
L.DomEvent.stopPropagation(e);
this.f(!this.active);
}
});
return function (config, map, router, buttons) {
var userLocation;
var locateUserButton = new LocateButton(function (d) {
if (d) {
enableTracking();
} else {
self.disableTracking();
}
});
var mybuttons = [];
function addButton(button) {
var el = button.onAdd();
mybuttons.push(el);
buttons.appendChild(el);
}
self.clearButtons = function clearButtons() {
mybuttons.forEach(function (d) {
buttons.removeChild(d);
});
};
var showCoordsPickerButton = new CoordsPickerButton(function (d) {
if (d) {
enableCoords();
} else {
disableCoords();
}
});
function enableTracking() {
map.locate({
watch: true,
enableHighAccuracy: true,
setView: true
});
locateUserButton.set(true);
}
self.disableTracking = function disableTracking() {
map.stopLocate();
self.locationError();
locateUserButton.set(false);
};
function enableCoords() {
map.getContainer().classList.add('pick-coordinates');
map.on('click', showCoordinates);
showCoordsPickerButton.set(true);
}
function disableCoords() {
map.getContainer().classList.remove('pick-coordinates');
map.off('click', showCoordinates);
showCoordsPickerButton.set(false);
}
function showCoordinates(e) {
router.fullUrl({ zoom: map.getZoom(), lat: e.latlng.lat, lng: e.latlng.lng });
disableCoords();
}
self.locationFound = function locationFound(e) {
if (!userLocation) {
userLocation = new LocationMarker(e.latlng).addTo(map);
}
userLocation.setLatLng(e.latlng);
userLocation.setAccuracy(e.accuracy);
};
self.locationError = function locationError() {
if (userLocation) {
map.removeLayer(userLocation);
userLocation = null;
}
};
self.init = function init() {
addButton(locateUserButton);
addButton(showCoordsPickerButton);
};
return self;
};
});

View File

@ -1,10 +1,19 @@
define(['leaflet', 'helper'], define(['leaflet', 'rbush', 'helper'],
function (L, helper) { function (L, rbush, helper) {
'use strict'; 'use strict';
return L.GridLayer.extend({ return L.GridLayer.extend({
setData: function (d) { mapRTree: function mapRTree(d) {
this.data = d; return {
minX: d.nodeinfo.location.latitude, minY: d.nodeinfo.location.longitude,
maxX: d.nodeinfo.location.latitude, maxY: d.nodeinfo.location.longitude,
node: d
};
},
setData: function (data) {
var rtreeOnlineAll = rbush(9);
this.data = rtreeOnlineAll.load(data.nodes.all.filter(helper.online).filter(helper.hasLocation).map(this.mapRTree));
// pre-calculate start angles // pre-calculate start angles
this.data.all().forEach(function (n) { this.data.all().forEach(function (n) {

View File

@ -1,7 +1,13 @@
define(['leaflet', 'rbush', 'helper'], define(['leaflet', 'rbush', 'helper', 'moment'],
function (L, rbush, helper) { function (L, rbush, helper, moment) {
'use strict'; 'use strict';
var groupOnline;
var groupOffline;
var groupNew;
var groupLost;
var groupLines;
var labelLocations = [['left', 'middle', 0 / 8], var labelLocations = [['left', 'middle', 0 / 8],
['center', 'top', 6 / 8], ['center', 'top', 6 / 8],
['right', 'middle', 4 / 8], ['right', 'middle', 4 / 8],
@ -43,7 +49,7 @@ define(['leaflet', 'rbush', 'helper'],
function calcOffset(offset, loc) { function calcOffset(offset, loc) {
return [offset * Math.cos(loc[2] * 2 * Math.PI), return [offset * Math.cos(loc[2] * 2 * Math.PI),
-offset * Math.sin(loc[2] * 2 * Math.PI)]; offset * Math.sin(loc[2] * 2 * Math.PI)];
} }
function labelRect(p, offset, anchor, label, minZoom, maxZoom, z) { function labelRect(p, offset, anchor, label, minZoom, maxZoom, z) {
@ -70,6 +76,59 @@ define(['leaflet', 'rbush', 'helper'],
return { minX: x, minY: y, maxX: x + width, maxY: y + height }; return { minX: x, minY: y, maxX: x + width, maxY: y + height };
} }
function mkMarker(dict, iconFunc, router) {
return function (d) {
var m = L.circleMarker([d.nodeinfo.location.latitude, d.nodeinfo.location.longitude], iconFunc(d));
m.resetStyle = function resetStyle() {
m.setStyle(iconFunc(d));
};
m.on('click', function () {
router.fullUrl({ node: d.nodeinfo.node_id });
});
m.bindTooltip(d.nodeinfo.hostname);
dict[d.nodeinfo.node_id] = m;
return m;
};
}
function addLinksToMap(dict, linkScale, graph, router) {
graph = graph.filter(function (d) {
return 'distance' in d && !d.vpn;
});
return graph.map(function (d) {
var opts = {
color: linkScale(1 / d.tq),
weight: 4,
opacity: 0.5,
dashArray: 'none'
};
var line = L.polyline(d.latlngs, opts);
line.resetStyle = function resetStyle() {
line.setStyle(opts);
};
line.bindTooltip(d.source.node.nodeinfo.hostname + ' ' + d.target.node.nodeinfo.hostname + '<br><strong>' + helper.showDistance(d) + ' / ' + helper.showTq(d) + '</strong>');
line.on('click', function () {
router.fullUrl({ link: d.id });
});
dict[d.id] = line;
return line;
});
}
function getIcon(config, color) {
return Object.assign({}, config.icon.base, config.icon[color]);
}
return L.GridLayer.extend({ return L.GridLayer.extend({
onAdd: function (map) { onAdd: function (map) {
L.GridLayer.prototype.onAdd.call(this, map); L.GridLayer.prototype.onAdd.call(this, map);
@ -77,8 +136,65 @@ define(['leaflet', 'rbush', 'helper'],
this.prepareLabels(); this.prepareLabels();
} }
}, },
setData: function (d) { setData: function (data, map, nodeDict, linkDict, linkScale, router, config) {
this.data = d; var iconOnline = getIcon(config, 'online');
var iconOffline = getIcon(config, 'offline');
var iconLost = getIcon(config, 'lost');
var iconAlert = getIcon(config, 'alert');
var iconNew = getIcon(config, 'new');
// Check if init or data is already set
if (groupLines) {
groupOffline.clearLayers();
groupOnline.clearLayers();
groupNew.clearLayers();
groupLost.clearLayers();
groupLines.clearLayers();
}
var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router);
groupLines = L.featureGroup(lines).addTo(map);
var nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new);
var nodesOffline = helper.subtract(data.nodes.all.filter(helper.offline), data.nodes.lost);
var markersOnline = nodesOnline.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconOnline;
}, router));
var markersOffline = nodesOffline.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconOffline;
}, router));
var markersNew = data.nodes.new.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function () {
return iconNew;
}, router));
var markersLost = data.nodes.lost.filter(helper.hasLocation)
.map(mkMarker(nodeDict, function (d) {
if (d.lastseen.isAfter(moment(data.now).subtract(config.maxAgeAlert, 'days'))) {
return iconAlert;
}
if (d.lastseen.isAfter(moment(data.now).subtract(config.maxAge, 'days'))) {
return iconLost;
}
return null;
}, router));
groupOffline = L.featureGroup(markersOffline).addTo(map);
groupLost = L.featureGroup(markersLost).addTo(map);
groupOnline = L.featureGroup(markersOnline).addTo(map);
groupNew = L.featureGroup(markersNew).addTo(map);
this.data = {
online: nodesOnline.filter(helper.hasLocation),
offline: nodesOffline.filter(helper.hasLocation),
new: data.nodes.new.filter(helper.hasLocation),
lost: data.nodes.lost.filter(helper.hasLocation)
};
this.updateLayer(); this.updateLayer();
}, },
updateLayer: function () { updateLayer: function () {