modules/ui/shortcuts.js (206 lines of code) (raw):
import {
select as d3_select,
selectAll as d3_selectAll
} from 'd3-selection';
import { t } from '../util/locale';
import { dataShortcuts } from '../../data';
import { svgIcon } from '../svg/icon';
import { uiCmd } from './cmd';
import { uiModal } from './modal';
import { utilArrayUniq } from '../util';
import { utilDetect } from '../util/detect';
export function uiShortcuts(context) {
var detected = utilDetect();
var _activeTab = 0;
var _modalSelection;
var _selection = d3_select(null);
context.keybinding()
.on([t('shortcuts.toggle.key'), '?'], function () {
if (d3_selectAll('.modal-shortcuts').size()) { // already showing
if (_modalSelection) {
_modalSelection.close();
_modalSelection = null;
}
} else {
_modalSelection = uiModal(_selection);
shortcutsModal(_modalSelection);
}
});
function shortcutsModal(_modalSelection) {
_modalSelection.select('.modal')
.classed('modal-shortcuts', true);
var shortcutsModal = _modalSelection.select('.content');
shortcutsModal
.append('div')
.attr('class', 'modal-section')
.append('h3')
.text(t('shortcuts.title'));
shortcutsModal
.call(render);
}
function render(selection) {
var wrapper = selection
.selectAll('.wrapper')
.data([0]);
var wrapperEnter = wrapper
.enter()
.append('div')
.attr('class', 'wrapper modal-section');
var tabsBar = wrapperEnter
.append('div')
.attr('class', 'tabs-bar');
var shortcutsList = wrapperEnter
.append('div')
.attr('class', 'shortcuts-list');
wrapper = wrapper.merge(wrapperEnter);
var tabs = tabsBar
.selectAll('.tab')
.data(dataShortcuts);
var tabsEnter = tabs
.enter()
.append('div')
.attr('class', 'tab')
.on('click', function (d, i) {
_activeTab = i;
render(selection);
});
tabsEnter
.append('span')
.text(function (d) { return t(d.text); });
tabs = tabs
.merge(tabsEnter);
// Update
wrapper.selectAll('.tab')
.classed('active', function (d, i) {
return i === _activeTab;
});
var shortcuts = shortcutsList
.selectAll('.shortcut-tab')
.data(dataShortcuts);
var shortcutsEnter = shortcuts
.enter()
.append('div')
.attr('class', function(d) { return 'shortcut-tab shortcut-tab-' + d.tab; });
var columnsEnter = shortcutsEnter
.selectAll('.shortcut-column')
.data(function (d) { return d.columns; })
.enter()
.append('table')
.attr('class', 'shortcut-column');
var rowsEnter = columnsEnter
.selectAll('.shortcut-row')
.data(function (d) { return d.rows; })
.enter()
.append('tr')
.attr('class', 'shortcut-row');
var sectionRows = rowsEnter
.filter(function (d) { return !d.shortcuts; });
sectionRows
.append('td');
sectionRows
.append('td')
.attr('class', 'shortcut-section')
.append('h3')
.text(function (d) { return t(d.text); });
var shortcutRows = rowsEnter
.filter(function (d) { return d.shortcuts; });
var shortcutKeys = shortcutRows
.append('td')
.attr('class', 'shortcut-keys');
var modifierKeys = shortcutKeys
.filter(function (d) { return d.modifiers; });
modifierKeys
.selectAll('kbd.modifier')
.data(function (d) {
if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
return ['⌘'];
} else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
return [];
} else {
return d.modifiers;
}
})
.enter()
.each(function () {
var selection = d3_select(this);
selection
.append('kbd')
.attr('class', 'modifier')
.text(function (d) { return uiCmd.display(d); });
selection
.append('span')
.text('+');
});
shortcutKeys
.selectAll('kbd.shortcut')
.data(function (d) {
var arr = d.shortcuts;
if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
arr = ['Y'];
} else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
arr = ['F11'];
}
// replace translations
arr = arr.map(function(s) {
return uiCmd.display(s.indexOf('.') !== -1 ? t(s) : s);
});
return utilArrayUniq(arr).map(function(s) {
return {
shortcut: s,
separator: d.separator,
suffix: d.suffix
};
});
})
.enter()
.each(function (d, i, nodes) {
var selection = d3_select(this);
var click = d.shortcut.toLowerCase().match(/(.*).click/);
if (click && click[1]) { // replace "left_click", "right_click" with mouse icon
selection
.call(svgIcon('#iD-walkthrough-mouse', 'mouseclick', click[1]));
} else {
selection
.append('kbd')
.attr('class', 'shortcut')
.text(function (d) { return d.shortcut; });
}
if (i < nodes.length - 1) {
selection
.append('span')
.text(d.separator || '\u00a0' + t('shortcuts.or') + '\u00a0');
} else if (i === nodes.length - 1 && d.suffix) {
selection
.append('span')
.text(d.suffix);
}
});
shortcutKeys
.filter(function(d) { return d.gesture; })
.each(function () {
var selection = d3_select(this);
selection
.append('span')
.text('+');
selection
.append('span')
.attr('class', 'gesture')
.text(function (d) { return t(d.gesture); });
});
shortcutRows
.append('td')
.attr('class', 'shortcut-desc')
.text(function (d) { return d.text ? t(d.text) : '\u00a0'; });
shortcuts = shortcuts
.merge(shortcutsEnter);
// Update
wrapper.selectAll('.shortcut-tab')
.style('display', function (d, i) {
return i === _activeTab ? 'flex' : 'none';
});
}
return function(selection, show) {
_selection = selection;
if (show) {
_modalSelection = uiModal(selection);
shortcutsModal(_modalSelection);
}
};
}