shortcut keys
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<div class="detail" id="{{id}}" data-scope="{{scope}}">
|
||||
<div class="detail" id="{{id}}" data-scope="{{scope}}" tabindex="-1">
|
||||
{{#unless buttonsDisabled}}
|
||||
<div class="detail-button-container button-container record-buttons clearfix">
|
||||
<div class="btn-group actions-btn-group" role="group">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="edit" id="{{id}}" data-scope="{{scope}}">
|
||||
<div class="edit" id="{{id}}" data-scope="{{scope}}" tabindex="-1">
|
||||
{{#unless buttonsDisabled}}
|
||||
<div class="detail-button-container button-container record-buttons clearfix">
|
||||
<div class="btn-group actions-btn-group" role="group">
|
||||
|
||||
@@ -375,10 +375,10 @@ define('views/modal', ['view'], function (Dep) {
|
||||
setupFinal: function () {
|
||||
if (this.shortcutKeys) {
|
||||
this.events['keydown.modal-base'] = e => {
|
||||
let key = e.key.toLowerCase();
|
||||
let key = e.code;
|
||||
|
||||
if (e.ctrlKey) {
|
||||
key = 'ctrl+' + key;
|
||||
key = 'Control+' + key;
|
||||
}
|
||||
|
||||
if (typeof this.shortcutKeys[key] === 'function') {
|
||||
|
||||
@@ -67,7 +67,7 @@ define('views/modals/detail', ['views/modal', 'helpers/action-item-setup'], func
|
||||
duplicateAction: false,
|
||||
|
||||
shortcutKeys: {
|
||||
'e': function (e) {
|
||||
'KeyE': function (e) {
|
||||
if (this.editDisabled) {
|
||||
return;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ define('views/modals/detail', ['views/modal', 'helpers/action-item-setup'], func
|
||||
this.actionEdit()
|
||||
.then(view => {
|
||||
view.$el
|
||||
.find('.form-control:not([disabled])')
|
||||
.find('.middle-tabs > button.active, .form-control, .form-control:not([disabled])')
|
||||
.first()
|
||||
.focus();
|
||||
});
|
||||
|
||||
@@ -58,6 +58,60 @@ define('views/modals/edit', ['views/modal'], function (Dep) {
|
||||
|
||||
bottomDisabled: false,
|
||||
|
||||
shortcutKeys: {
|
||||
'Control+Enter': function (e) {
|
||||
if (this.saveDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buttonList.findIndex(item => item.name === 'save' && !item.hidden) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionSave();
|
||||
},
|
||||
'Control+KeyS': function (e) {
|
||||
if (this.saveDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buttonList.findIndex(item => item.name === 'save' && !item.hidden) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionSaveAndContinueEditing();
|
||||
},
|
||||
'Escape': function (e) {
|
||||
if (this.saveDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
let focusedFieldView = this.getRecordView().getFocusedFieldView();
|
||||
|
||||
if (focusedFieldView) {
|
||||
this.model.set(focusedFieldView.fetch());
|
||||
}
|
||||
|
||||
if (this.getRecordView().isChanged) {
|
||||
this.confirm(this.translate('confirmLeaveOutMessage', 'messages'))
|
||||
.then(() => this.actionClose());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.actionClose();
|
||||
},
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
this.buttonList = [];
|
||||
|
||||
@@ -71,45 +125,6 @@ define('views/modals/edit', ['views/modal'], function (Dep) {
|
||||
label: 'Save',
|
||||
style: 'primary',
|
||||
});
|
||||
|
||||
this.events['keydown'] = (e) => {
|
||||
if (e.key === 'Enter' && e.ctrlKey) {
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionSave();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((e.key === 's' || e.key === 'S') && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionSaveAndContinueEditing();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
let focusedFieldView = this.getRecordView().getFocusedFieldView();
|
||||
|
||||
if (focusedFieldView) {
|
||||
this.model.set(focusedFieldView.fetch());
|
||||
}
|
||||
|
||||
if (this.getRecordView().isChanged) {
|
||||
this.confirm(this.translate('confirmLeaveOutMessage', 'messages'))
|
||||
.then(() => this.actionClose());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.actionClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.fullFormDisabled = this.options.fullFormDisabled || this.fullFormDisabled;
|
||||
|
||||
@@ -417,13 +417,16 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
* @type {?Object.<string,string|function (JQueryKeyEventObject): void>}
|
||||
*/
|
||||
shortcutKeys: {
|
||||
'ctrl+enter': function (e) {
|
||||
'Control+Enter': function (e) {
|
||||
this.handleShortcutKeyCtrlEnter(e);
|
||||
},
|
||||
'ctrl+s': function (e) {
|
||||
'Control+KeyS': function (e) {
|
||||
this.handleShortcutKeyCtrlS(e);
|
||||
},
|
||||
'escape': function (e) {
|
||||
'KeyE': function (e) {
|
||||
this.handleShortcutKeyE(e);
|
||||
},
|
||||
'Escape': function (e) {
|
||||
this.handleShortcutKeyEscape(e);
|
||||
},
|
||||
},
|
||||
@@ -496,6 +499,7 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
if (!this.lastSaveCancelReason || this.lastSaveCancelReason === 'notModified') {
|
||||
this.setDetailMode();
|
||||
|
||||
this.focusOnFirstDiv();
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
},
|
||||
@@ -503,9 +507,14 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
actionCancelEdit: function () {
|
||||
this.cancelEdit();
|
||||
|
||||
this.focusOnFirstDiv();
|
||||
$(window).scrollTop(0);
|
||||
},
|
||||
|
||||
focusOnFirstDiv: function () {
|
||||
this.$el.find('> div').focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* A `save-and-continue-editing` action.
|
||||
*/
|
||||
@@ -1891,10 +1900,10 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
if (this.shortcutKeys && this.options.shortcutKeysEnabled) {
|
||||
// @todo Move to util (the same for the `views/modal`.).
|
||||
this.events['keydown.record-detail'] = e => {
|
||||
let key = e.key.toLowerCase();
|
||||
let key = e.code;
|
||||
|
||||
if (e.ctrlKey) {
|
||||
key = 'ctrl+' + key;
|
||||
key = 'Control+' + key;
|
||||
}
|
||||
|
||||
if (typeof this.shortcutKeys[key] === 'function') {
|
||||
@@ -1916,6 +1925,8 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
|
||||
this[methodName]();
|
||||
};
|
||||
|
||||
this.once('after:render', () => this.focusOnFirstDiv());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3392,91 +3403,6 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
.find('.dropdown-edit-item-list-button');
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {JQueryKeyEventObject} e
|
||||
*/
|
||||
handleKeydownEvent: function (e) {
|
||||
if (!this.options.shortcutKeysEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (e.key === 'Enter' && e.ctrlKey) {
|
||||
if (this.inlineEditModeIsOn || this.buttonsDisabled || !this.shortcutEnterAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.mode !== this.MODE_EDIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.type === this.TYPE_DETAIL &&
|
||||
this.buttonEditList.findIndex(item => item.name === this.shortcutEnterAction) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.type === this.TYPE_EDIT &&
|
||||
this.buttonList.findIndex(item => item.name === this.shortcutEnterAction) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
let methodName = 'action' + Espo.Utils.upperCaseFirst(this.shortcutEnterAction);
|
||||
|
||||
this[methodName]();
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
/*if ((e.key === 's' || e.key === 'S') && e.ctrlKey) {
|
||||
if (this.inlineEditModeIsOn || this.buttonsDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.mode !== this.MODE_EDIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.saveAndContinueEditingAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionSaveAndContinueEditing();
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
if (this.inlineEditModeIsOn || this.buttonsDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.type === this.TYPE_DETAIL && this.mode === this.MODE_EDIT) {
|
||||
e.stopPropagation();
|
||||
|
||||
// Fetching a currently edited form element.
|
||||
this.model.set(this.fetch());
|
||||
|
||||
if (this.isChanged) {
|
||||
this.confirm(this.translate('confirmLeaveOutMessage', 'messages'))
|
||||
.then(() => this.actionCancelEdit());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.actionCancelEdit();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {JQueryKeyEventObject} e
|
||||
@@ -3494,14 +3420,14 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
|
||||
if (
|
||||
this.type === this.TYPE_DETAIL &&
|
||||
this.buttonEditList.findIndex(item => item.name === action) === -1
|
||||
this.buttonEditList.findIndex(item => item.name === action && !item.hidden) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.type === this.TYPE_EDIT &&
|
||||
this.buttonList.findIndex(item => item.name === action) === -1
|
||||
this.buttonList.findIndex(item => item.name === action && !item.hidden) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -3537,6 +3463,38 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
|
||||
this.actionSaveAndContinueEditing();
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {JQueryKeyEventObject} e
|
||||
*/
|
||||
handleShortcutKeyE: function (e) {
|
||||
if (this.inlineEditModeIsOn || this.buttonsDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.type !== this.TYPE_DETAIL || this.mode !== this.MODE_DETAIL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buttonList.findIndex(item => item.name === 'edit' && !item.hidden) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(e.currentTarget)
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.actionEdit();
|
||||
|
||||
if (!this.editModeDisabled) {
|
||||
setTimeout(() => {
|
||||
this.$el.find('.middle-tabs > button.active, .form-control:not([disabled])')
|
||||
.first().focus();
|
||||
}, 200);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {JQueryKeyEventObject} e
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.record > div[tabindex="-1"]:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
.record .record-grid {
|
||||
grid-column-gap: @padding-base-horizontal;
|
||||
|
||||
Reference in New Issue
Block a user