mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
Don't match shiftKey strictly, but prioritize shifted over unshifted
Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
so we don't strictly match on the shift key, but we prioritize
shifted bindings first, and fallback to unshifted only if no match.
(This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
This commit is contained in:
@@ -14,44 +14,73 @@ import _ from 'lodash';
|
||||
export function d3keybinding(namespace) {
|
||||
var bindings = [];
|
||||
|
||||
function matches(binding, event) {
|
||||
if (event.key !== undefined) {
|
||||
if (binding.event.key === undefined) {
|
||||
return false;
|
||||
} else if (_.isArray(binding.event.key)) {
|
||||
if (binding.event.key.map(function(s) { return s.toLowerCase(); }).indexOf(event.key.toLowerCase()) === -1)
|
||||
return false;
|
||||
} else {
|
||||
if (event.key.toLowerCase() !== binding.event.key.toLowerCase())
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// check keycodes if browser doesn't support KeyboardEvent.key
|
||||
if (event.keyCode !== binding.event.keyCode)
|
||||
return false;
|
||||
}
|
||||
// check modifier keys
|
||||
for (var p in binding.event.modifiers) {
|
||||
if (event[p] !== binding.event.modifiers[p])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function testBindings(isCapturing) {
|
||||
for (var i = 0; i < bindings.length; i++) {
|
||||
var binding = bindings[i];
|
||||
var didMatch = false,
|
||||
i, binding;
|
||||
|
||||
if (!!binding.capture === isCapturing && matches(binding, d3.event)) {
|
||||
// Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
|
||||
// so we don't strictly match on the shift key, but we prioritize
|
||||
// shifted bindings first, and fallback to unshifted only if no match.
|
||||
// (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
|
||||
|
||||
// priority match shifted bindings first
|
||||
for (i = 0; i < bindings.length; i++) {
|
||||
binding = bindings[i];
|
||||
if (!binding.event.modifiers.shiftKey) continue; // no shift
|
||||
if (!!binding.capture !== isCapturing) continue;
|
||||
if (matches(binding, true)) {
|
||||
binding.callback();
|
||||
didMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
// then unshifted bindings
|
||||
if (didMatch) return;
|
||||
for (i = 0; i < bindings.length; i++) {
|
||||
binding = bindings[i];
|
||||
if (binding.event.modifiers.shiftKey) continue; // shift
|
||||
if (!!binding.capture !== isCapturing) continue;
|
||||
if (matches(binding, false)) {
|
||||
binding.callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function matches(binding, testShift) {
|
||||
var event = d3.event;
|
||||
if (event.key !== undefined) {
|
||||
if (binding.event.key === undefined) {
|
||||
return false;
|
||||
} else if (_.isArray(binding.event.key)) {
|
||||
if (binding.event.key.map(function(s) { return s.toLowerCase(); }).indexOf(event.key.toLowerCase()) === -1)
|
||||
return false;
|
||||
} else {
|
||||
if (event.key.toLowerCase() !== binding.event.key.toLowerCase())
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// check keycodes if browser doesn't support KeyboardEvent.key
|
||||
if (event.keyCode !== binding.event.keyCode)
|
||||
return false;
|
||||
}
|
||||
|
||||
// test modifier keys
|
||||
if (event.ctrlKey !== binding.event.modifiers.ctrlKey) return false;
|
||||
if (event.altKey !== binding.event.modifiers.altKey) return false;
|
||||
if (event.metaKey !== binding.event.modifiers.metaKey) return false;
|
||||
if (testShift && event.shiftKey !== binding.event.modifiers.shiftKey) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function capture() {
|
||||
testBindings(true);
|
||||
}
|
||||
|
||||
|
||||
function bubble() {
|
||||
var tagName = d3.select(d3.event.target).node().tagName;
|
||||
if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
|
||||
@@ -60,6 +89,7 @@ export function d3keybinding(namespace) {
|
||||
testBindings(false);
|
||||
}
|
||||
|
||||
|
||||
function keybinding(selection) {
|
||||
selection = selection || d3.select(document);
|
||||
selection.on('keydown.capture' + namespace, capture, true);
|
||||
@@ -67,6 +97,7 @@ export function d3keybinding(namespace) {
|
||||
return keybinding;
|
||||
}
|
||||
|
||||
|
||||
keybinding.off = function(selection) {
|
||||
bindings = [];
|
||||
selection = selection || d3.select(document);
|
||||
@@ -75,6 +106,7 @@ export function d3keybinding(namespace) {
|
||||
return keybinding;
|
||||
};
|
||||
|
||||
|
||||
keybinding.on = function(codes, callback, capture) {
|
||||
var arr = [].concat(codes);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user