Merge pull request #314 from rkflx/pr/add-and-fix-shortcuts
Add more keyboard shortcuts and fix various shortcut related issues
This commit is contained in:
commit
77f1b5f0af
17 changed files with 433 additions and 107 deletions
|
|
@ -7,7 +7,10 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
bottom: 30,
|
||||
left: 60
|
||||
},
|
||||
theme: 'steelblue-theme'
|
||||
theme: 'steelblue-theme',
|
||||
shortcut: {
|
||||
toggle: 69 // char code for 'e'
|
||||
}
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
|
|
@ -30,6 +33,8 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
L.DomEvent.on(this._container, 'mouseup', this._dragEndHandler, this);
|
||||
}
|
||||
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
|
|
@ -64,5 +69,11 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
|
||||
layer.on('mouseout', this._hidePositionMarker.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggle) {
|
||||
$('#elevation-btn').click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
BR.NogoAreas = L.Control.extend({
|
||||
options: {
|
||||
shortcut: {
|
||||
draw: {
|
||||
enable: 78, // char code for 'n'
|
||||
disable: 27 // char code for 'ESC'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
statics: {
|
||||
MSG_BUTTON: 'Draw no-go area (circle)',
|
||||
MSG_BUTTON_CANCEL: 'Cancel drawing no-go area',
|
||||
|
|
@ -48,28 +57,32 @@ BR.NogoAreas = L.Control.extend({
|
|||
featuresLayer: this.drawnItems
|
||||
}));
|
||||
|
||||
this.startDrawing = function(control) {
|
||||
// initial radius of 0 to detect click, see DeletableCircleEditor.onDrawingMouseUp
|
||||
var opts = L.extend({ radius: 0 }, self.style);
|
||||
editTools.startCircle(null, opts);
|
||||
|
||||
control.state('cancel-no-go-create');
|
||||
};
|
||||
|
||||
this.stopDrawing = function(control) {
|
||||
editTools.stopDrawing();
|
||||
control.state('no-go-create');
|
||||
};
|
||||
|
||||
this.button = L.easyButton({
|
||||
states: [
|
||||
{
|
||||
stateName: BR.NogoAreas.STATE_CREATE,
|
||||
icon: 'fa-ban',
|
||||
title: BR.NogoAreas.MSG_BUTTON,
|
||||
onClick: function(control) {
|
||||
// initial radius of 0 to detect click, see DeletableCircleEditor.onDrawingMouseUp
|
||||
var opts = L.extend({ radius: 0 }, self.style);
|
||||
editTools.startCircle(null, opts);
|
||||
|
||||
control.state('cancel-no-go-create');
|
||||
}
|
||||
onClick: this.startDrawing
|
||||
},
|
||||
{
|
||||
stateName: BR.NogoAreas.STATE_CANCEL,
|
||||
icon: 'fa-ban active',
|
||||
title: BR.NogoAreas.MSG_BUTTON_CANCEL,
|
||||
onClick: function(control) {
|
||||
editTools.stopDrawing();
|
||||
control.state('no-go-create');
|
||||
}
|
||||
onClick: this.stopDrawing
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
@ -78,6 +91,8 @@ BR.NogoAreas = L.Control.extend({
|
|||
// events firing in Chrome mobile while L.Map.Tap enabled for circle drawing
|
||||
L.DomEvent.addListener(this.button.button, 'pointerdown', L.DomEvent.stop);
|
||||
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
|
||||
this.editTools.on(
|
||||
'editable:drawing:end',
|
||||
function(e) {
|
||||
|
|
@ -124,6 +139,20 @@ BR.NogoAreas = L.Control.extend({
|
|||
return L.DomUtil.create('div');
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (!BR.Util.keyboardShortcutsAllowed(e)) {
|
||||
return;
|
||||
}
|
||||
if (e.keyCode === this.options.shortcut.draw.disable && this.button.state() === BR.NogoAreas.STATE_CANCEL) {
|
||||
this.stopDrawing(this.button);
|
||||
} else if (
|
||||
e.keyCode === this.options.shortcut.draw.enable &&
|
||||
this.button.state() === BR.NogoAreas.STATE_CREATE
|
||||
) {
|
||||
this.startDrawing(this.button);
|
||||
}
|
||||
},
|
||||
|
||||
displayUploadError: function(message) {
|
||||
$('#nogoError').text(message ? message : '');
|
||||
$('#nogoError').css('display', message ? 'block' : 'none');
|
||||
|
|
|
|||
|
|
@ -42,11 +42,9 @@ BR.PoiMarkers = L.Control.extend({
|
|||
self.draw(false);
|
||||
});
|
||||
|
||||
var container = new L.DomUtil.create('div');
|
||||
// keys not working when map container does not have focus, use document instead
|
||||
L.DomEvent.removeListener(container, 'keyup', this._keyupListener);
|
||||
L.DomEvent.addListener(document, 'keyup', this._keyupListener, this);
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
|
||||
var container = new L.DomUtil.create('div');
|
||||
return container;
|
||||
},
|
||||
|
||||
|
|
@ -62,9 +60,8 @@ BR.PoiMarkers = L.Control.extend({
|
|||
}
|
||||
},
|
||||
|
||||
_keyupListener: function(e) {
|
||||
// Suppress shortcut handling when a text input field is focussed
|
||||
if (document.activeElement.type == 'text' || document.activeElement.type == 'textarea') {
|
||||
_keydownListener: function(e) {
|
||||
if (!BR.Util.keyboardShortcutsAllowed(e)) {
|
||||
return;
|
||||
}
|
||||
if (e.keyCode === this.options.shortcut.draw.disable) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ BR.Routing = L.Routing.extend({
|
|||
textFunction: function(distance) {
|
||||
return distance / 1000;
|
||||
}
|
||||
},
|
||||
shortcut: {
|
||||
draw: {
|
||||
enable: 68, // char code for 'd'
|
||||
disable: 27 // char code for 'ESC'
|
||||
},
|
||||
reverse: 82, // char code for 'r'
|
||||
deleteLastPoint: 90 // char code for 'z'
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -163,8 +171,7 @@ BR.Routing = L.Routing.extend({
|
|||
this._draw
|
||||
);
|
||||
|
||||
// keys not working when map container does not have focus, use document instead
|
||||
L.DomEvent.removeListener(this._container, 'keyup', this._keyupListener);
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
L.DomEvent.addListener(document, 'keyup', this._keyupListener, this);
|
||||
|
||||
// enable drawing mode
|
||||
|
|
@ -336,16 +343,26 @@ BR.Routing = L.Routing.extend({
|
|||
return segments;
|
||||
},
|
||||
|
||||
_keyupListener: function(e) {
|
||||
// Suppress shortcut handling when a text input field is focussed
|
||||
if (document.activeElement.type == 'text' || document.activeElement.type == 'textarea') {
|
||||
_keydownListener: function(e) {
|
||||
if (!BR.Util.keyboardShortcutsAllowed(e)) {
|
||||
return;
|
||||
}
|
||||
// add 'esc' to disable drawing
|
||||
if (e.keyCode === 27) {
|
||||
if (e.keyCode === this.options.shortcut.draw.disable) {
|
||||
this._draw.disable();
|
||||
} else {
|
||||
L.Routing.prototype._keyupListener.call(this, e);
|
||||
} else if (e.keyCode === this.options.shortcut.draw.enable) {
|
||||
this._draw.enable();
|
||||
} else if (e.keyCode === this.options.shortcut.reverse) {
|
||||
this.reverse();
|
||||
} else if (e.keyCode === this.options.shortcut.deleteLastPoint) {
|
||||
this.deleteLastPoint();
|
||||
}
|
||||
},
|
||||
|
||||
_keyupListener: function(e) {
|
||||
// Prevent Leaflet from triggering drawing a second time on keyup,
|
||||
// since this is already done in _keydownListener
|
||||
if (e.keyCode === this.options.shortcut.draw.enable) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -360,6 +377,12 @@ BR.Routing = L.Routing.extend({
|
|||
this.setWaypoints(waypoints);
|
||||
},
|
||||
|
||||
deleteLastPoint: function() {
|
||||
if ((lastPoint = this.getLast())) {
|
||||
this.removeWaypoint(lastPoint, function(err, data) {});
|
||||
}
|
||||
},
|
||||
|
||||
_removeDistanceMarkers: function() {
|
||||
if (this._map && this._distanceMarkers) {
|
||||
this._map.removeLayer(this._distanceMarkers);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
BR.RoutingPathQuality = L.Control.extend({
|
||||
options: {
|
||||
shortcut: {
|
||||
toggle: 67, // char code for 'c'
|
||||
muteKeyCode: 77 // char code for 'm'
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function(map, layersControl, options) {
|
||||
L.setOptions(this, options);
|
||||
|
||||
|
|
@ -78,6 +85,7 @@ BR.RoutingPathQuality = L.Control.extend({
|
|||
this.selectedProvider = this._initialProvider;
|
||||
|
||||
this._active = false;
|
||||
this._muted = false;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
|
|
@ -133,6 +141,11 @@ BR.RoutingPathQuality = L.Control.extend({
|
|||
});
|
||||
}
|
||||
|
||||
if (this.options.shortcut.muteKeyCode || this.options.shortcut.toggle) {
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
L.DomEvent.addListener(document, 'keyup', this._keyupListener, this);
|
||||
}
|
||||
|
||||
this.routingPathButton = new L.easyButton({
|
||||
states: states
|
||||
}).addTo(map);
|
||||
|
|
@ -177,6 +190,26 @@ BR.RoutingPathQuality = L.Control.extend({
|
|||
this._routingSegments.addLayer(layers[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (!BR.Util.keyboardShortcutsAllowed(e)) {
|
||||
return;
|
||||
}
|
||||
if (this._active && e.keyCode === this.options.shortcut.muteKeyCode) {
|
||||
this._muted = true;
|
||||
this._deactivate(this.routingPathButton);
|
||||
}
|
||||
if (!this._muted && e.keyCode === this.options.shortcut.toggle) {
|
||||
this.routingPathButton.button.click();
|
||||
}
|
||||
},
|
||||
|
||||
_keyupListener: function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && this._muted && e.keyCode === this.options.shortcut.muteKeyCode) {
|
||||
this._muted = false;
|
||||
this._activate(this.routingPathButton);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,21 @@ BR.Search = L.Control.Geocoder.extend({
|
|||
}),
|
||||
sizeInMeters: 800
|
||||
}),
|
||||
position: 'topleft'
|
||||
position: 'topleft',
|
||||
shortcut: {
|
||||
search: 70 // char code for 'f'
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
L.Control.Geocoder.prototype.initialize.call(this, options);
|
||||
L.setOptions(this, {
|
||||
// i18next.t will only return 'undefined' if it is called in a static context
|
||||
// (e.g. when added directly to "options:" above), so we have to call it here
|
||||
placeholder: i18next.t('map.geocoder-placeholder')
|
||||
});
|
||||
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
},
|
||||
|
||||
markGeocode: function(result) {
|
||||
|
|
@ -29,5 +43,12 @@ BR.Search = L.Control.Geocoder.extend({
|
|||
if (this._geocodeMarker) {
|
||||
this._map.removeLayer(this._geocodeMarker);
|
||||
}
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.search) {
|
||||
$('#map .leaflet-control-geocoder')[0].dispatchEvent(new MouseEvent('mousedown'));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ BR.Sidebar = L.Control.Sidebar.extend({
|
|||
autopan: false,
|
||||
defaultTabId: '',
|
||||
|
||||
shortcut: {
|
||||
toggleTabs: 84 // char code for 't'
|
||||
},
|
||||
|
||||
// Tabs to be notified when shown or hidden
|
||||
// (tab div id -> object implementing show/hide methods)
|
||||
listeningTabs: {}
|
||||
|
|
@ -17,6 +21,8 @@ BR.Sidebar = L.Control.Sidebar.extend({
|
|||
L.Control.Sidebar.prototype.initialize.call(this, id, options);
|
||||
|
||||
this.oldTab = null;
|
||||
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
},
|
||||
|
||||
addTo: function(map) {
|
||||
|
|
@ -34,6 +40,15 @@ BR.Sidebar = L.Control.Sidebar.extend({
|
|||
this
|
||||
);
|
||||
|
||||
this.recentTab = this.options.defaultTabId;
|
||||
this.on(
|
||||
'content',
|
||||
function(tab) {
|
||||
this.recentTab = tab.id;
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
this._rememberTabState();
|
||||
|
||||
if (L.Browser.touch && BR.Browser.touchScreenDetectable && !BR.Browser.touchScreen) {
|
||||
|
|
@ -103,6 +118,30 @@ BR.Sidebar = L.Control.Sidebar.extend({
|
|||
|
||||
_storeActiveTab: function(e) {
|
||||
localStorage.setItem(this.storageId, e.id || '');
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggleTabs) {
|
||||
if ($('#sidebarTabs > ul > li[class=active]').length) {
|
||||
// sidebar is currently open
|
||||
if (e.shiftKey) {
|
||||
// try to find next tab
|
||||
var nextTab = $('#sidebarTabs > ul > li[class=active] ~ li:not([hidden]) > a');
|
||||
if (!nextTab.length) {
|
||||
// wrap around to first tab
|
||||
nextTab = $('#sidebarTabs > ul > li:not([hidden]) > a');
|
||||
}
|
||||
// switch to next or first tab
|
||||
this.open(nextTab.attr('href').slice(1));
|
||||
} else {
|
||||
// close current tab
|
||||
this.close();
|
||||
}
|
||||
} else {
|
||||
// sidebar is currently closed, open recent or default tab
|
||||
this.open(this.recentTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@ BR.tracksLoader = function(map, layersControl, routing) {
|
|||
},
|
||||
addToMap: false,
|
||||
// File size limit in kb (default: 1024) ?
|
||||
fileSizeLimit: 1024
|
||||
fileSizeLimit: 1024,
|
||||
shortcut: {
|
||||
open: 79 // char code for 'o'
|
||||
}
|
||||
},
|
||||
|
||||
_initContainer: function() {
|
||||
|
|
@ -31,6 +34,8 @@ BR.tracksLoader = function(map, layersControl, routing) {
|
|||
var fileInput;
|
||||
var container = L.DomUtil.get('navbarLoadTracksContainer');
|
||||
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
|
||||
// Create an invisible file input
|
||||
fileInput = L.DomUtil.create('input', 'hidden', container);
|
||||
fileInput.type = 'file';
|
||||
|
|
@ -62,6 +67,16 @@ BR.tracksLoader = function(map, layersControl, routing) {
|
|||
var dummy = L.DomUtil.create('div');
|
||||
dummy.hidden = true;
|
||||
return dummy;
|
||||
},
|
||||
|
||||
_keydownListener: function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.open) {
|
||||
if (e.shiftKey) {
|
||||
$('#loadNogos').modal('show');
|
||||
} else {
|
||||
$('#navbarLoadTracks')[0].click();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
var tracksLoaderControl = new TracksLoader();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ BR.stravaSegments = function(map, layersControl) {
|
|||
);
|
||||
};
|
||||
|
||||
L.setOptions(this, {
|
||||
shortcut: {
|
||||
toggleLayer: 83 // char code for 's'
|
||||
}
|
||||
});
|
||||
|
||||
// hide strava buttons when layer is inactive
|
||||
var toggleStravaControl = function() {
|
||||
var stravaBar = stravaControl.runningButton.button.parentElement;
|
||||
|
|
@ -24,5 +30,20 @@ BR.stravaSegments = function(map, layersControl) {
|
|||
toggleStravaControl();
|
||||
stravaControl.stravaLayer.on('add remove', toggleStravaControl);
|
||||
|
||||
L.DomEvent.addListener(
|
||||
document,
|
||||
'keydown',
|
||||
function(e) {
|
||||
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggleLayer) {
|
||||
if (map.hasLayer(stravaControl.stravaLayer)) {
|
||||
map.removeLayer(stravaControl.stravaLayer);
|
||||
} else {
|
||||
map.addLayer(stravaControl.stravaLayer);
|
||||
}
|
||||
}
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
return stravaControl;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue