# # 自定义快捷键

## # 概述

为了让应用层方便地自定义快捷键，Foxit PDF SDK for Web 提供了如 `PDFViewer.onShortcutKey` 等接口。本文将介绍如何使用这些接口以及相关注意事项。

### # 名词定义

为了避免混淆，在开始之前我们定义了以下术语在文档中的语义：

1. 组合键：表示特定的按键组合，例如 `Ctrl+Z` 是一个组合键，`Cmd+Z` 是另一个组合键。

2. 快捷键：表示能够触发特定功能的组合键，例如，撤销操作的快捷键是 `Ctrl+Z` 或 `Cmd+Z`。

## # 内置的组合键及描述

在这里，我们列出了 Foxit PDF SDK for Web 中内置的组合键。开发者可以参考此表格，在应用层通过替换内置实现来自定义组合键。

组合键 | 描述
--- | ---
`Esc` | 关闭对话框，退出编辑模式或退出搜索面板。
`Home` | 跳转到第一页。
`End` | 跳转到最后一页。
`Delete` | 删除选定的对象。编辑模式下：删除选定的文本对象；非编辑模式下：删除选定的注释对象。
`PageUp` | 当存在垂直滚动条时, 将当前视图向上移动。
`PageDown` | 当存在垂直滚动条时, 将当前视图向下移动。
`UpArrow` | 当存在垂直滚动条时, 将滚动条向上移动。
`DownArrow` | 当存在垂直滚动条时, 将滚动条向下移动。
`LeftArrow` | 当存在水平滚动条时, 将滚动条向左移动。
`RightArrow` | 当存在水平滚动条时, 将滚动条向右移动。
`Enter` | 确认或继续。
`Ctrl+Z` | 撤销。Mac 平台为`Cmd+Z`。
`Ctrl+Y` | 重做。Mac 平台为`Cmd+Shift+Z`。
`Ctrl+MouseLeft` | 选择多个对象、注释、路径、文本编辑。
`Ctrl+F` | 打开搜索面板。Mac 平台为`Cmd+F`。
`Ctrl+P` | 打开打印面板。Mac 平台为`Cmd+P`。
`Ctrl+RightArrow` | 打开左侧导航面板。Mac 平台为`Cmd+RightArrow`。
`Ctrl+LeftArrow` | 关闭左侧导航面板。Mac 平台为`Cmd+LeftArrow`。
`Ctrl+C` | 复制注释（路径、文本编辑、图像）。Mac 平台为`Cmd+C`。
`Ctrl+X` | 剪切注释（文本）。Mac 平台为`Cmd+X`。
`Ctrl+V` | 粘贴注释（路径、文本编辑、图像）。Mac 平台为`Cmd+V`。

## # 开始自定义

开发者可以通过 `PDFViewer.onShortcutKey` 接口添加快捷键事件处理函数。如果接收到的快捷键已在 SDK 内定义（如上表所列），将 `preventDefaultImplementation` 参数设置为 `true` 将替换 SDK 内部快捷键的实现。否则，当触发快捷键时，SDK 内部实现和开发者自定义的处理函数将同时执行。

### # 替换内置快捷键实现

这里我们以打印功能的快捷键为例：

    <script>
        const libPath = window.top.location.origin + '/lib';
        const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
        const pdfui = new UIExtension.PDFUI({
            viewerOptions: {
                libPath: libPath,
                jr: {
                    licenseSN: licenseSN,
                    licenseKey: licenseKey
                }
            },
            renderTo: document.body,
            appearance: UIExtension.appearances.adaptive,
            addons: libPath + '/uix-addons/allInOne.js'
        });
        pdfui.onShortcutKey("Ctrl+P", function() {
            pdfui.getComponentByName('print-dialog').then(printDialog => {
                if(printDialog) {
                    printDialog.show();
                }
            })
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

在上述示例中，替换了 SDK 中快捷键的内置实现。当用户按下 `Ctrl+P` 组合键时，将触发自定义打印实现。您可以在该实现中获取到 `print-dialog` 显示打印对话框，或使用其他方法来实现自定义打印功能。

### # 替换组合键

如果您不想使用 `Ctrl+P` 触发打印功能，则需要替换 SDK 中的内置实现，并注册一个自定义的快捷键来实现打印功能。以下是示例代码：

    <script>
        const libPath = window.top.location.origin + '/lib';
        const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
        const pdfui = new UIExtension.PDFUI({
            viewerOptions: {
                libPath: libPath,
                jr: {
                    licenseSN: licenseSN,
                    licenseKey: licenseKey
                }
            },
            renderTo: document.body,
            appearance: UIExtension.appearances.adaptive,
            addons: libPath + '/uix-addons/allInOne.js'
        });
        pdfui.onShortcutKey('Ctrl+P', function() {
            // PASS
        }, true);
        pdfui.onShortcutKey('Ctrl+Alt+P', function(e) {
            pdfui.print({
                pages: [0]
            });
        })
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

在上述示例中，首先使用 `PDFViewer.onShortcutKey` 注册一个空函数，以替换 SDK 中 `Ctrl+P` 的内置实现。然后，再为 `Ctrl+Alt+P` 注册一个事件监听器，当用户按下 `Ctrl+Alt+P` 时，将调用 `pdfui.print()` 方法来实现打印功能。

需要注意的是，在替换快捷键的内置实现时，应将 `onShortcutKey` 接口的第三个参数设置为 `true`。这样，自定义实现将替换 SDK 的默认内置实现，而不是与之并存。

### # 删除快捷键监听事件

在某些情况下，您可能需要在特定条件下删除快捷键监听事件。例如，在文档打开时，您可以监听 `Ctrl+W` 事件来关闭文档。但在文档关闭后，您需要取消 `Ctrl+W` 事件的监听，以避免不必要的操作。为此，`PDFViewer.onShortcutKey` 接口会返回一个函数，您可以使用该函数来删除快捷键事件的监听。以下是一个示例：

    <script>
        const libPath = window.top.location.origin + '/lib';
        const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
        const pdfui = new UIExtension.PDFUI({
            viewerOptions: {
                libPath: libPath,
                jr: {
                    licenseSN: licenseSN,
                    licenseKey: licenseKey
                }
            },
            renderTo: document.body,
            appearance: UIExtension.appearances.adaptive,
            addons: libPath + '/uix-addons/allInOne.js'
        });
        var removeShortcutKeyHandler = () => {};
        pdfui.addViewerEventListener(UIExtension.PDFViewCtrl.ViewerEvents.openFileSuccess, () => {
            removeShortcutKeyHandler();
            pdfui.onShortcutKey('Ctrl+Shift+K', function(e) {
                e.preventDefault();// 阻止浏览器原生的默认实现
                pdfui.close(); // 用户关闭文档
            }).then((remove) => {
                removeShortcutKeyHandler = remove;
            })
        });
        pdfui.addViewerEventListener(UIExtension.PDFViewCtrl.ViewerEvents.willCloseDocument, () => {
            removeShortcutKeyHandler();
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

在上述示例中，首先在 `openFileSuccess` 事件回调中使用 `PDFViewer.onShortcutKey` 监听 `Ctrl+Shift+K` 事件，并将返回的函数保存到变量 `removeShortcutKeyHandler` 中。当要关闭文档时，可以调用 `removeShortcutKeyHandler` 函数来删除对 `Ctrl+Shift+K` 事件的监听。

需要注意的是，如果您使用了多个 `PDFViewer.onShortcutKey` 监听事件，每个事件都会返回一个相应的函数，您需要分别保存每个函数，并在需要时分别调用它们。

### # 禁用/启用全局快捷键

在某些情况下，您可能需要禁用快捷键功能，可以通过使用 `setEnableShortcutKey` 接口来实现。该接口接受一个布尔值参数。如果为 true，则启用快捷键功能，如果为 false ，则禁用快捷键功能。

    <script>
        const libPath = window.top.location.origin + '/lib';
        const FRAGMENT_ACTION = UIExtension.UIConsts.FRAGMENT_ACTION;
        const pdfui = new UIExtension.PDFUI({
            viewerOptions: {
                libPath: libPath,
                jr: {
                    licenseSN: licenseSN,
                    licenseKey: licenseKey
                }
            },
            renderTo: document.body,
            appearance: UIExtension.appearances.adaptive,
            addons: libPath + '/uix-addons/allInOne.js'
        });
        pdfui.setEnableShortcutKey(false);
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px"
        }
    }

上述示例禁用了快捷键功能，则所有的组合键都将不会被触发。要重新启用快捷键功能，您可以调用 `pdfui.setEnableShortcutKey(true)`。

## # 注意事项

为了更符合 Mac 用户的使用习惯，我们在 Mac 平台上使用了不同的组合鍵。通常情况下，我们使用 `Cmd` 键代替 `Ctrl` 键。例如，在 Windows/Linux 上，"撤销"的快捷键是 `Ctrl+Z`，而在 Mac 上则是 `Cmd+Z`。

如果您想替换"撤销"功能的快捷键，需要根据系统类型选择这两个组合键中的一个来监听快捷键事件。