mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
Rewrite d3.keybinding
A keybinding now represents a set of key commands that can be unbound as a set. Multiple keybindings are possible, and, providing a namespace is provided to the constructor, will not conflict with each other. Also, key combination strings such as ⌘+A are now supported.
This commit is contained in:
32
js/id/id.js
32
js/id/id.js
@@ -184,26 +184,18 @@ window.iD = function(container) {
|
||||
map.size(m.size());
|
||||
});
|
||||
|
||||
map.keybinding()
|
||||
.on('a', function(evt, mods) {
|
||||
if (mods) return;
|
||||
controller.enter(iD.modes.AddArea());
|
||||
})
|
||||
.on('⌫.prevent_navigation', function(evt, mods) {
|
||||
evt.preventDefault();
|
||||
})
|
||||
.on('p', function(evt, mods) {
|
||||
if (mods) return;
|
||||
controller.enter(iD.modes.AddPoint());
|
||||
})
|
||||
.on('l', function(evt, mods) {
|
||||
if (mods) return;
|
||||
controller.enter(iD.modes.AddLine());
|
||||
})
|
||||
.on('z', function(evt, mods) {
|
||||
if (mods === '⇧⌘' || mods === '⌃⇧') history.redo();
|
||||
if (mods === '⌘' || mods === '⌃') history.undo();
|
||||
});
|
||||
var keybinding = d3.keybinding('main')
|
||||
.on('P', function() { controller.enter(iD.modes.AddPoint()); })
|
||||
.on('L', function() { controller.enter(iD.modes.AddLine()); })
|
||||
.on('A', function() { controller.enter(iD.modes.AddArea()); })
|
||||
.on('⌘+Z', function() { history.undo(); })
|
||||
.on('⌃+Z', function() { history.undo(); })
|
||||
.on('⌘+⇧+Z', function() { history.redo(); })
|
||||
.on('⌃+⇧+Z', function() { history.redo(); })
|
||||
.on('⌫', function(e) { e.preventDefault(); });
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
var hash = iD.Hash().controller(controller).map(map);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ iD.modes.AddArea = function() {
|
||||
description: 'Add parks, buildings, lakes, or other areas to the map.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-area');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
@@ -38,9 +40,12 @@ iD.modes.AddArea = function() {
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
});
|
||||
|
||||
map.keybinding().on('⎋.addarea', function() {
|
||||
keybinding.on('⎋', function() {
|
||||
controller.exit();
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
@@ -49,7 +54,7 @@ iD.modes.AddArea = function() {
|
||||
}, 1000);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addarea', null);
|
||||
mode.map.keybinding().on('⎋.addarea', null);
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -6,6 +6,8 @@ iD.modes.AddLine = function() {
|
||||
description: 'Lines can be highways, streets, pedestrian paths, or even canals.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-line');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
node,
|
||||
@@ -60,16 +62,19 @@ iD.modes.AddLine = function() {
|
||||
controller.enter(iD.modes.DrawLine(way.id, direction));
|
||||
});
|
||||
|
||||
map.keybinding().on('⎋.addline', function() {
|
||||
keybinding.on('⎋', function() {
|
||||
controller.exit();
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addline', null);
|
||||
mode.map.keybinding().on('⎋.addline', null);
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -5,6 +5,8 @@ iD.modes.AddPoint = function() {
|
||||
description: 'Restaurants, monuments, and postal boxes are points.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-point');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
@@ -22,15 +24,18 @@ iD.modes.AddPoint = function() {
|
||||
controller.enter(iD.modes.Select(node, true));
|
||||
});
|
||||
|
||||
map.keybinding().on('⎋.addpoint', function() {
|
||||
keybinding.on('⎋', function() {
|
||||
controller.exit();
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addpoint', null);
|
||||
mode.map.keybinding().on('⎋.addpoint', null);
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -4,6 +4,8 @@ iD.modes.DrawArea = function(wayId) {
|
||||
id: 'draw-area'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('draw-area');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
@@ -102,11 +104,14 @@ iD.modes.DrawArea = function(wayId) {
|
||||
.on('mouseover.drawarea', mouseover)
|
||||
.on('click.drawarea', click);
|
||||
|
||||
map.keybinding()
|
||||
.on('⌫.drawarea', backspace)
|
||||
.on('⌦.drawarea', del)
|
||||
.on('⎋.drawarea', ret)
|
||||
.on('↩.drawarea', ret);
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
.on('⌦', del)
|
||||
.on('⎋', ret)
|
||||
.on('↩', ret);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
@@ -122,11 +127,7 @@ iD.modes.DrawArea = function(wayId) {
|
||||
.on('mousemove.drawarea', null)
|
||||
.on('click.drawarea', null);
|
||||
|
||||
mode.map.keybinding()
|
||||
.on('⎋.drawarea', null)
|
||||
.on('⌫.drawarea', null)
|
||||
.on('⌦.drawarea', null)
|
||||
.on('↩.drawarea', null);
|
||||
keybinding.off();
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
|
||||
@@ -4,6 +4,8 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
id: 'draw-line'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('draw-line');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
@@ -133,16 +135,19 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
.on('mousemove.drawline', mousemove)
|
||||
.on('click.drawline', click);
|
||||
|
||||
map.keybinding()
|
||||
.on('⌫.drawline', backspace)
|
||||
.on('⌦.drawline', del)
|
||||
.on('⎋.drawline', ret)
|
||||
.on('↩.drawline', ret)
|
||||
.on('z.drawline', function(evt, mods) {
|
||||
if (mods === '⌘' || mods === '⌃') undo();
|
||||
});
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
.on('⌦', del)
|
||||
.on('⎋', ret)
|
||||
.on('↩', ret)
|
||||
.on('⌘-Z', undo)
|
||||
.on('⌃-Z', undo);
|
||||
|
||||
d3.select('#undo').on('click.drawline', undo);
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
d3.select('#undo')
|
||||
.on('click.drawline', undo);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
@@ -159,12 +164,7 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
.on('mousemove.drawline', null)
|
||||
.on('click.drawline', null);
|
||||
|
||||
mode.map.keybinding()
|
||||
.on('⌫.drawline', null)
|
||||
.on('⌦.drawline', null)
|
||||
.on('⎋.drawline', null)
|
||||
.on('↩.drawline', null)
|
||||
.on('z.drawline', null);
|
||||
keybinding.off();
|
||||
|
||||
d3.select('#undo').on('click.drawline', null);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ iD.modes.Select = function(entity, initial) {
|
||||
};
|
||||
|
||||
var inspector = iD.ui.inspector().initial(!!initial),
|
||||
keybinding = d3.keybinding('select'),
|
||||
behaviors;
|
||||
|
||||
function remove() {
|
||||
@@ -132,10 +133,10 @@ iD.modes.Select = function(entity, initial) {
|
||||
surface.on('click.select', click)
|
||||
.on('dblclick.browse', dblclick);
|
||||
|
||||
mode.map.keybinding().on('⌫.select', function(e) {
|
||||
remove();
|
||||
e.preventDefault();
|
||||
});
|
||||
keybinding.on('⌫', remove);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
surface.selectAll("*")
|
||||
.filter(function (d) {
|
||||
@@ -166,8 +167,9 @@ iD.modes.Select = function(entity, initial) {
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
location.hash = '#' + iD.util.qsString(_.omit(q, 'id'), true);
|
||||
|
||||
keybinding.off();
|
||||
|
||||
surface.on("click.select", null);
|
||||
mode.map.keybinding().on('⌫.select', null);
|
||||
mode.history.on('change.entity-undone', null);
|
||||
|
||||
surface.selectAll(".selected")
|
||||
|
||||
@@ -2,7 +2,6 @@ iD.Map = function() {
|
||||
var connection, history,
|
||||
dimensions = [],
|
||||
dispatch = d3.dispatch('move', 'drawn'),
|
||||
keybinding = d3.keybinding(),
|
||||
projection = d3.geo.mercator().scale(1024),
|
||||
roundedProjection = iD.svg.RoundProjection(projection),
|
||||
zoom = d3.behavior.zoom()
|
||||
@@ -49,8 +48,6 @@ iD.Map = function() {
|
||||
|
||||
supersurface
|
||||
.call(tail);
|
||||
|
||||
d3.select(document).call(keybinding);
|
||||
}
|
||||
|
||||
function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
|
||||
@@ -345,12 +342,6 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.keybinding = function (_) {
|
||||
if (!arguments.length) return keybinding;
|
||||
keybinding = _;
|
||||
return map;
|
||||
};
|
||||
|
||||
map.background = background;
|
||||
map.projection = projection;
|
||||
map.redraw = redraw;
|
||||
|
||||
@@ -1,120 +1,197 @@
|
||||
d3.keybinding = function() {
|
||||
// via https://github.com/keithamus/jwerty/
|
||||
// and https://github.com/madrobby/keymaster
|
||||
var _keys = {
|
||||
// MOD aka toggleable keys
|
||||
mods: {
|
||||
// Shift key, ⇧
|
||||
'⇧': 16,
|
||||
// CTRL key, on Mac: ⌃
|
||||
'⌃': 17,
|
||||
// ALT key, on Mac: ⌥ (Alt)
|
||||
'⌥': 18,
|
||||
// META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
|
||||
'⌘': 91
|
||||
},
|
||||
// Normal keys
|
||||
keys: {
|
||||
// Backspace key, on Mac: ⌫ (Backspace)
|
||||
'⌫': 8, backspace: 8,
|
||||
// Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
|
||||
'⇥': 9, '⇆': 9, tab: 9,
|
||||
// Return key, ↩
|
||||
'↩': 13, 'return': 13, enter: 13, '⌅': 13,
|
||||
// Pause/Break key
|
||||
'pause': 19, 'pause-break': 19,
|
||||
// Caps Lock key, ⇪
|
||||
'⇪': 20, caps: 20, 'caps-lock': 20,
|
||||
// Escape key, on Mac: ⎋, on Windows: Esc
|
||||
'⎋': 27, escape: 27, esc: 27,
|
||||
// Space key
|
||||
space: 32,
|
||||
// Page-Up key, or pgup, on Mac: ↖
|
||||
'↖': 33, pgup: 33, 'page-up': 33,
|
||||
// Page-Down key, or pgdown, on Mac: ↘
|
||||
'↘': 34, pgdown: 34, 'page-down': 34,
|
||||
// END key, on Mac: ⇟
|
||||
'⇟': 35, end: 35,
|
||||
// HOME key, on Mac: ⇞
|
||||
'⇞': 36, home: 36,
|
||||
// Insert key, or ins
|
||||
ins: 45, insert: 45,
|
||||
// Delete key, on Mac: ⌦ (Delete)
|
||||
'⌦': 46, del: 46, 'delete': 46,
|
||||
// Left Arrow Key, or ←
|
||||
'←': 37, left: 37, 'arrow-left': 37,
|
||||
// Up Arrow Key, or ↑
|
||||
'↑': 38, up: 38, 'arrow-up': 38,
|
||||
// Right Arrow Key, or →
|
||||
'→': 39, right: 39, 'arrow-right': 39,
|
||||
// Up Arrow Key, or ↓
|
||||
'↓': 40, down: 40, 'arrow-down': 40,
|
||||
// odities, printing characters that come out wrong:
|
||||
// Num-Multiply, or *
|
||||
'*': 106, star: 106, asterisk: 106, multiply: 106,
|
||||
// Num-Plus or +
|
||||
'+': 107, 'plus': 107,
|
||||
// Num-Subtract, or -
|
||||
'-': 109, subtract: 109,
|
||||
// Semicolon
|
||||
';': 186, semicolon:186,
|
||||
// = or equals
|
||||
'=': 187, 'equals': 187,
|
||||
// Comma, or ,
|
||||
',': 188, comma: 188,
|
||||
//'-': 189, //???
|
||||
// Period, or ., or full-stop
|
||||
'.': 190, period: 190, 'full-stop': 190,
|
||||
// Slash, or /, or forward-slash
|
||||
'/': 191, slash: 191, 'forward-slash': 191,
|
||||
// Tick, or `, or back-quote
|
||||
'`': 192, tick: 192, 'back-quote': 192,
|
||||
// Open bracket, or [
|
||||
'[': 219, 'open-bracket': 219,
|
||||
// Back slash, or \
|
||||
'\\': 220, 'back-slash': 220,
|
||||
// Close backet, or ]
|
||||
']': 221, 'close-bracket': 221,
|
||||
// Apostraphe, or Quote, or '
|
||||
'\'': 222, quote: 222, apostraphe: 222
|
||||
/*
|
||||
* This code is licensed under the MIT license.
|
||||
*
|
||||
* Copyright © 2013, iD authors.
|
||||
*
|
||||
* Portions copyright © 2011, Keith Cirkel
|
||||
* See https://github.com/keithamus/jwerty
|
||||
*
|
||||
*/
|
||||
d3.keybinding = function(namespace) {
|
||||
var bindings = [];
|
||||
|
||||
function matches(binding, event) {
|
||||
for (var p in binding.event) {
|
||||
if (event[p] != binding.event[p])
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// To minimise code bloat, add all of the NUMPAD 0-9 keys in a loop
|
||||
var i = 95, n = 0;
|
||||
while (++i < 106) _keys.keys['num-' + n] = i; ++n;
|
||||
// To minimise code bloat, add all of the top row 0-9 keys in a loop
|
||||
i = 47, n = 0;
|
||||
while (++i < 58) _keys.keys[n] = i; ++n;
|
||||
// To minimise code bloat, add all of the F1-F25 keys in a loop
|
||||
i = 111, n = 1;
|
||||
while (++i < 136) _keys.keys['f' + n] = i; ++n;
|
||||
// To minimise code bloat, add all of the letters of the alphabet in a loop
|
||||
i = 64;
|
||||
while(++i < 91) _keys.keys[String.fromCharCode(i).toLowerCase()] = i;
|
||||
|
||||
var pairs = d3.entries(_keys.keys),
|
||||
event = d3.dispatch.apply(d3, d3.keys(_keys.keys));
|
||||
|
||||
function keys(selection) {
|
||||
selection.on('keydown', function () {
|
||||
var tagName = d3.select(d3.event.target).node().tagName;
|
||||
if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
|
||||
var modifiers = '';
|
||||
if (d3.event.shiftKey) modifiers += '⇧';
|
||||
if (d3.event.ctrlKey) modifiers += '⌃';
|
||||
if (d3.event.altKey) modifiers += '⌥';
|
||||
if (d3.event.metaKey) modifiers += '⌘';
|
||||
|
||||
pairs.filter(function(d) {
|
||||
return d.value === d3.event.keyCode;
|
||||
}).forEach(function(d) {
|
||||
event[d.key](d3.event, modifiers);
|
||||
});
|
||||
});
|
||||
return (!binding.capture) === (event.eventPhase !== Event.CAPTURING_PHASE);
|
||||
}
|
||||
|
||||
return d3.rebind(keys, event, 'on');
|
||||
function capture() {
|
||||
for (var i = 0; i < bindings.length; i++) {
|
||||
var binding = bindings[i];
|
||||
if (matches(binding, d3.event)) {
|
||||
binding.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bubble() {
|
||||
var tagName = d3.select(d3.event.target).node().tagName;
|
||||
if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
capture();
|
||||
}
|
||||
|
||||
function keybinding(selection) {
|
||||
selection = selection || d3.select(document);
|
||||
selection.on('keydown.capture' + namespace, capture, true);
|
||||
selection.on('keydown.bubble' + namespace, bubble, false);
|
||||
return keybinding;
|
||||
}
|
||||
|
||||
keybinding.off = function(selection) {
|
||||
selection = selection || d3.select(document);
|
||||
selection.on('keydown.capture' + namespace, null);
|
||||
selection.on('keydown.bubble' + namespace, null);
|
||||
return keybinding;
|
||||
};
|
||||
|
||||
keybinding.on = function(code, callback, capture) {
|
||||
var binding = {
|
||||
event: {
|
||||
keyCode: 0,
|
||||
shiftKey: false,
|
||||
ctrlKey: false,
|
||||
altKey: false,
|
||||
metaKey: false
|
||||
},
|
||||
capture: capture,
|
||||
callback: callback
|
||||
};
|
||||
|
||||
code = code.toLowerCase().match(/(?:(?:[^+])+|\+\+|^\+$)/g);
|
||||
|
||||
for (var i = 0; i < code.length; i++) {
|
||||
// Normalise matching errors
|
||||
if (code[i] === '++') code[i] = '+';
|
||||
|
||||
if (code[i] in d3.keybinding.modifierCodes) {
|
||||
binding.event[d3.keybinding.modifierProperties[d3.keybinding.modifierCodes[code[i]]]] = true;
|
||||
} else if (code[i] in d3.keybinding.keyCodes) {
|
||||
binding.event.keyCode = d3.keybinding.keyCodes[code[i]];
|
||||
}
|
||||
}
|
||||
|
||||
bindings.push(binding);
|
||||
|
||||
return keybinding;
|
||||
};
|
||||
|
||||
return keybinding;
|
||||
};
|
||||
|
||||
(function () {
|
||||
d3.keybinding.modifierCodes = {
|
||||
// Shift key, ⇧
|
||||
'⇧': 16, shift: 16,
|
||||
// CTRL key, on Mac: ⌃
|
||||
'⌃': 17, ctrl: 17,
|
||||
// ALT key, on Mac: ⌥ (Alt)
|
||||
'⌥': 18, alt: 18, option: 18,
|
||||
// META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
|
||||
'⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
|
||||
};
|
||||
|
||||
d3.keybinding.modifierProperties = {
|
||||
16: 'shiftKey',
|
||||
17: 'ctrlKey',
|
||||
18: 'altKey',
|
||||
91: 'metaKey'
|
||||
};
|
||||
|
||||
d3.keybinding.keyCodes = {
|
||||
// Backspace key, on Mac: ⌫ (Backspace)
|
||||
'⌫': 8, backspace: 8,
|
||||
// Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
|
||||
'⇥': 9, '⇆': 9, tab: 9,
|
||||
// Return key, ↩
|
||||
'↩': 13, 'return': 13, enter: 13, '⌅': 13,
|
||||
// Pause/Break key
|
||||
'pause': 19, 'pause-break': 19,
|
||||
// Caps Lock key, ⇪
|
||||
'⇪': 20, caps: 20, 'caps-lock': 20,
|
||||
// Escape key, on Mac: ⎋, on Windows: Esc
|
||||
'⎋': 27, escape: 27, esc: 27,
|
||||
// Space key
|
||||
space: 32,
|
||||
// Page-Up key, or pgup, on Mac: ↖
|
||||
'↖': 33, pgup: 33, 'page-up': 33,
|
||||
// Page-Down key, or pgdown, on Mac: ↘
|
||||
'↘': 34, pgdown: 34, 'page-down': 34,
|
||||
// END key, on Mac: ⇟
|
||||
'⇟': 35, end: 35,
|
||||
// HOME key, on Mac: ⇞
|
||||
'⇞': 36, home: 36,
|
||||
// Insert key, or ins
|
||||
ins: 45, insert: 45,
|
||||
// Delete key, on Mac: ⌦ (Delete)
|
||||
'⌦': 46, del: 46, 'delete': 46,
|
||||
// Left Arrow Key, or ←
|
||||
'←': 37, left: 37, 'arrow-left': 37,
|
||||
// Up Arrow Key, or ↑
|
||||
'↑': 38, up: 38, 'arrow-up': 38,
|
||||
// Right Arrow Key, or →
|
||||
'→': 39, right: 39, 'arrow-right': 39,
|
||||
// Up Arrow Key, or ↓
|
||||
'↓': 40, down: 40, 'arrow-down': 40,
|
||||
// odities, printing characters that come out wrong:
|
||||
// Num-Multiply, or *
|
||||
'*': 106, star: 106, asterisk: 106, multiply: 106,
|
||||
// Num-Plus or +
|
||||
'+': 107, 'plus': 107,
|
||||
// Num-Subtract, or -
|
||||
'-': 109, subtract: 109,
|
||||
// Semicolon
|
||||
';': 186, semicolon:186,
|
||||
// = or equals
|
||||
'=': 187, 'equals': 187,
|
||||
// Comma, or ,
|
||||
',': 188, comma: 188,
|
||||
//'-': 189, //???
|
||||
// Period, or ., or full-stop
|
||||
'.': 190, period: 190, 'full-stop': 190,
|
||||
// Slash, or /, or forward-slash
|
||||
'/': 191, slash: 191, 'forward-slash': 191,
|
||||
// Tick, or `, or back-quote
|
||||
'`': 192, tick: 192, 'back-quote': 192,
|
||||
// Open bracket, or [
|
||||
'[': 219, 'open-bracket': 219,
|
||||
// Back slash, or \
|
||||
'\\': 220, 'back-slash': 220,
|
||||
// Close backet, or ]
|
||||
']': 221, 'close-bracket': 221,
|
||||
// Apostrophe, or Quote, or '
|
||||
'\'': 222, quote: 222, apostrophe: 222
|
||||
};
|
||||
|
||||
// NUMPAD 0-9
|
||||
var i = 95, n = 0;
|
||||
while (++i < 106) {
|
||||
d3.keybinding.keyCodes['num-' + n] = i;
|
||||
++n;
|
||||
}
|
||||
|
||||
// 0-9
|
||||
i = 47; n = 0;
|
||||
while (++i < 58) {
|
||||
d3.keybinding.keyCodes[n] = i;
|
||||
++n;
|
||||
}
|
||||
|
||||
// F1-F25
|
||||
i = 111; n = 1;
|
||||
while (++i < 136) {
|
||||
d3.keybinding.keyCodes['f' + n] = i;
|
||||
++n;
|
||||
}
|
||||
|
||||
// a-z
|
||||
i = 64;
|
||||
while (++i < 91) {
|
||||
d3.keybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -124,6 +124,8 @@
|
||||
<script src="spec/spec_helpers.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script src="spec/lib/d3.keybinding.js"></script>
|
||||
|
||||
<script src="spec/actions/add_node.js"></script>
|
||||
<script src="spec/actions/add_relation_member.js"></script>
|
||||
<script src="spec/actions/add_way.js"></script>
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
evt = new Event(o.type);
|
||||
evt.keyCode = o.keyCode || 0;
|
||||
evt.charCode = o.charCode || 0;
|
||||
evt.shift = o.shift || false;
|
||||
evt.meta = o.meta || false;
|
||||
evt.ctrl = o.ctrl || false;
|
||||
evt.alt = o.alt || false;
|
||||
evt.shiftKey = o.shiftKey || false;
|
||||
evt.metaKey = o.metaKey || false;
|
||||
evt.ctrlKey = o.ctrlKey || false;
|
||||
evt.altKey = o.altKey || false;
|
||||
} else {
|
||||
evt = document.createEvent('KeyboardEvent');
|
||||
// https://developer.mozilla.org/en/DOM/event.initKeyEvent
|
||||
@@ -33,10 +33,10 @@
|
||||
true, // in boolean canBubbleArg,
|
||||
true, // in boolean cancelableArg,
|
||||
null, // in nsIDOMAbstractView viewArg, Specifies UIEvent.view. This value may be null.
|
||||
o.ctrl || false, // in boolean ctrlKeyArg,
|
||||
o.alt || false, // in boolean altKeyArg,
|
||||
o.shift || false, // in boolean shiftKeyArg,
|
||||
o.meta || false, // in boolean metaKeyArg,
|
||||
o.ctrlKey || false, // in boolean ctrlKeyArg,
|
||||
o.altKey || false, // in boolean altKeyArg,
|
||||
o.shiftKey || false, // in boolean shiftKeyArg,
|
||||
o.metaKey || false, // in boolean metaKeyArg,
|
||||
o.keyCode || 0, // in unsigned long keyCodeArg,
|
||||
o.charCode || 0 // in unsigned long charCodeArg);
|
||||
);
|
||||
@@ -53,10 +53,10 @@
|
||||
o.screenY || 0, // screenY
|
||||
o.clientX || 0, // clientX
|
||||
o.clientY || 0, // clientY
|
||||
o.ctrl || 0, // ctrl
|
||||
o.alt || false, // alt
|
||||
o.shift || false, // shift
|
||||
o.meta || false, // meta
|
||||
o.ctrlKey || 0, // ctrl
|
||||
o.altKey || false, // alt
|
||||
o.shiftKey || false, // shift
|
||||
o.metaKey || false, // meta
|
||||
o.button || false, // mouse button
|
||||
null // relatedTarget
|
||||
);
|
||||
@@ -65,7 +65,8 @@
|
||||
x.dispatchEvent(evt);
|
||||
};
|
||||
|
||||
var shortcuts = ['click', 'mousedown', 'mouseup', 'mousemove', 'keydown', 'keyup', 'keypress'],
|
||||
var shortcuts = ['click', 'mousedown', 'mouseup', 'mousemove',
|
||||
'mouseover', 'mouseout', 'keydown', 'keyup', 'keypress'],
|
||||
s, i = 0;
|
||||
|
||||
while (s = shortcuts[i++]) {
|
||||
|
||||
55
test/spec/lib/d3.keybinding.js
Normal file
55
test/spec/lib/d3.keybinding.js
Normal file
@@ -0,0 +1,55 @@
|
||||
describe("d3.keybinding", function() {
|
||||
var keybinding, spy, input;
|
||||
|
||||
beforeEach(function () {
|
||||
keybinding = d3.keybinding('keybinding-test');
|
||||
spy = sinon.spy();
|
||||
input = d3.select('body')
|
||||
.append('input');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
keybinding.off(d3.select(document));
|
||||
input.remove();
|
||||
});
|
||||
|
||||
describe("#on", function () {
|
||||
it("returns self", function () {
|
||||
expect(keybinding.on('a', spy)).to.equal(keybinding);
|
||||
});
|
||||
|
||||
it("adds a binding for the specified bare key", function () {
|
||||
d3.select(document).call(keybinding.on('A', spy));
|
||||
|
||||
happen.keydown(document, {keyCode: 65, metaKey: true});
|
||||
expect(spy).not.to.have.been.called;
|
||||
|
||||
happen.keydown(document, {keyCode: 65});
|
||||
expect(spy).to.have.been.called;
|
||||
});
|
||||
|
||||
it("adds a binding for the specified key combination", function () {
|
||||
d3.select(document).call(keybinding.on('⌘+A', spy));
|
||||
|
||||
happen.keydown(document, {keyCode: 65});
|
||||
expect(spy).not.to.have.been.called;
|
||||
|
||||
happen.keydown(document, {keyCode: 65, metaKey: true});
|
||||
expect(spy).to.have.been.called;
|
||||
});
|
||||
|
||||
it("does not dispatch when focus is in input elements by default", function () {
|
||||
d3.select(document).call(keybinding.on('A', spy));
|
||||
|
||||
happen.keydown(input.node(), {keyCode: 65});
|
||||
expect(spy).not.to.have.been.called;
|
||||
});
|
||||
|
||||
it("dispatches when focus is in input elements when the capture flag was passed", function () {
|
||||
d3.select(document).call(keybinding.on('A', spy, true));
|
||||
|
||||
happen.keydown(input.node(), {keyCode: 65});
|
||||
expect(spy).to.have.been.called;
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user