Keyboard shortcuts for extensible controls

Keyboard shortcuts are an important consideration when you create any extensible control. This article provides information that will help you choose keyboard shortcuts for your extensible controls. It also outlines the recommended method for implementing keyboard shortcuts for extensible controls.

Overview

For accessibility, it's essential that keyboard-only users be able to use controls. Therefore, keyboard shortcuts are an important consideration when you create any extensible control. This article provides information that will help you choose key combinations to use as keyboard shortcuts. It highlights the shortcuts that are currently used by finance and operations apps and supported browsers, shortcuts that are planned for implementation, and shortcuts that one or more browsers don't allow to be overridden. This article also outlines the recommended way to implement keyboard shortcuts for extensible controls.

Choosing a key combination

When you're trying to choose a key combination to use as a keyboard shortcut, it's important that you be aware of other existing shortcuts. In this way, you help guarantee that your shortcut won't overlap an existing shortcut. If you try to collide with an existing shortcut, one of the following outcomes might occur:

  • The new keyboard shortcut might not work, because a browser doesn't allow that key combination to be overridden, or a framework-provided shortcut takes precedence over the new shortcut.
  • The new keyboard shortcut might remove expected keyboard functionality, because users expect specific key combinations to perform specific functions in a browser. Alternatively, you might override framework-provided shortcuts or other control shortcuts, so that keyboard-only users can't use them.

Because of these potential issues, we recommend that you adhere to this guidance when you choose a key combination:

  • Don't choose any key combination that is currently used by finance and operations apps, or that is planned for future implementation.
  • Do pick key combinations that will work in all supported browsers.
  • Do be careful when you override shortcuts that are used by a supported browser. You should not suppress shortcuts for important or frequently used browser functionality.
  • Do use longer key combinations (three keys) for control-specific behavior. Shorter combinations should be reserved for user-defined keyboard shortcuts.
  • Don't choose any key combination that involves Ctrl+Alt, because this combination maps to Alt+Gr for some Eastern European languages and will conflict with other shortcuts.

Here are links to the keyboard shortcuts that are documented for finance and operations apps and supported browsers:

Planned keyboard shortcuts

In addition to the keyboard shortcuts that are currently used, there are several shortcuts that are planned for future implementation. To avoid conflicts with framework-provided shortcuts, you should not choose the following key combinations for extensible controls.

Shortcut Functionality
F3 Move to the nearest QuickFilter.
Alt+F3 Add a filter that is based on the value of the current control (Filter by value).
Alt+Shift+F3 Clear all user-defined filters.
F6 Move to the nearest toolbar.
Shift+F7 Move to the toast message.

Browser/operating system keyboard shortcuts to avoid

Keyboard shortcuts that correspond to important functionality

The following table provides a short, non-exhaustive list of keyboard shortcuts that correspond to important functionality in a browser or operating system. You should not choose the key combinations in this table.

Shortcut Functionality
Ctrl+A Select all the text in the current field, or select all content on the page.
Ctrl+C Copy.
Ctrl+V Paste.
Ctrl+X Cut.
F5 Refresh the page.
Ctrl+F5 Refresh the page, and ignore cached content.
Shift+F10 Simulate a right-click.
Tab / Shift+Tab Move to the next/previous control.
Ctrl+Tab / Ctrl+Shift+Tab Move to the next/previous browser tab.
Alt+Tab / Alt+Shift+Tab Move to the next/previous application.
Alt+Right arrow / Alt + Left arrow Go to the next/previous page in the browser history.

Keyboard shortcuts that can't be overridden by some browsers

Some browsers don't allow the following keyboard shortcuts to be overridden. Therefore, you should not choose the following key combinations, because the shortcut won't work in all browsers.

Alt+A Alt+T Ctrl+F4 Alt+Tab
Alt+C Alt+V Alt+F5 Alt+Shift+Tab
Alt+D Ctrl+W Alt+F6 Spacebar
Alt+Shift+D Ctrl+Shift+W Alt+Shift+F6 Alt+Shift+Backspace
Alt+E Alt+X F12 Ctrl+Pause/Break
Alt+F Ctrl+Shift+0 Ctrl+Esc Ctrl+Shift+Pause/Break
Alt+H Ctrl+Shift+7 Ctrl+Shift+Esc Ctrl+Page up
Ctrl+N F1 Alt+Esc Ctrl+Page down
Ctrl+Shift+N Ctrl+F1 Alt+Shift+Esc Ctrl+Plus sign (+)
Ctrl+Shift+Q Ctrl+Shift+F1 Ctrl+Tab Shift+Plus sign (+)
Ctrl+T Shift+F1 Ctrl+Shift+Tab Ctrl+Minus sign (–)

Implementing keyboard shortcuts

We recommend that you use the registration mechanism that is described in this section to implement keyboard shortcuts. There are several benefits to registering a control's shortcuts in this manner:

  • You specify only the modifier keys that you want. If any other modifiers are pressed, the shortcut won't run. Therefore, a keyboard shortcut that is defined for Ctrl+Down arrow won't be triggered if Ctrl+Shift+Down arrow is pressed.
  • You can reuse code.
  • If you return false from the handler function, propagation won't stop on the event. If you return true (or if you don't specify a return value), propagation will stop.
  • Ctrl and Meta modifiers are treated the same. Therefore, you can specify keyboard shortcuts that will work for both iOS and Microsoft Windows. For example, the shortcut Ctrl+G on Windows will be translated to Meta+G on iOS.
  • Built-in telemetry for the keyboard shortcuts is used.

Define a keyboard shortcut

  1. Define a Shortcuts object on the control's prototype. Then define the keyboard shortcuts inside the Shortcuts object. These shortcuts should have the following structure. Make sure that the key code that you're trying to use is defined in the $dyn.ui.KeyCodes object.

    Shortcuts: {
        Name: {
            Keys: { modifier1: true, modifier2:true, 
                keyCode: $dyn.ui.KeyCodes.* }, 
            // Only specify the modifiers you need 
            // (between alt, ctrl/meta, shift)
            Handler: function (evt) {
                // Code to handle shortcut.
            },
            // Additional code.
    }
    

    If more than one key code should apply to your keyboard shortcut, pass in an array of codes, as shown here.

    Keys: {modifier1:true, 
        keyCode:[$dyn.ui.KeyCodes.*, $dyn.ui.KeyCodes.*, ... ] } 
    // Note: If any of these keyCodes match then the handler is called. I.E. 
    // The keyCodes in the array are OR'd not AND'd
    
  2. Add the keydown handler by using the following code.

    keydown: function (event) {
        $dyn.util.handleShortcuts(this, event);
    },
    
  3. Bind the keyDown handler. The keyDown handler is automatically bound for form objects. Other controls must be manually bound to the keyDown handler, as for any regular binding.

    Important

    "keyDown" is case sensitive.

    <div data-dyn-bind="keyDown: $data.keydown"></div>;
    

Examples

Here is a Form example.

Shortcuts: {
    Save: {
        Keys: { ctrl: true, keyCode: $dyn.ui.KeyCodes.letterS },
        Handler: function (evt) {
            var control = evt ? $dyn.context(evt.target) : undefined;
            this.executeShortcuts(true, "SaveRecord", control);
        },
    },
    New: {
        Keys: { alt: true, keyCode: $dyn.ui.KeyCodes.letterN },
        Handler: function (evt) {
            var control = evt ? $dyn.context(evt.target) : undefined;
            this.executeShortcuts(true, "NewRecord", control);
        },
    },
    Delete: {
        Keys: { alt: true, keyCode: $dyn.ui.KeyCodes.deleteKey },
        Handler: function (evt) {
            this.executeShortcuts(false, "DeleteRecord");
        },
    },
    // Additional code
}

Here is a Dialogs example that extends the Form control.

Shortcuts: $dyn.extendPrototype($dyn.controls.Form.prototype.Shortcuts, {
    InvokeDefaultButton: {
        Keys: { keyCode: $dyn.ui.KeyCodes.enter },
        Handler: function (evt) {
            this.executeShortcuts(false, "InvokeDefaultButton");
        }
    },
})