Browse Source

Merge pull request #8308 from electron/normalize-access-keys

Support normalizing access keys in dialog buttons
Kevin Sawicki 8 years ago
parent
commit
0a7dccbad8
2 changed files with 35 additions and 0 deletions
  1. 8 0
      docs/api/dialog.md
  2. 27 0
      lib/browser/api/dialog.js

+ 8 - 0
docs/api/dialog.md

@@ -35,6 +35,14 @@ The `dialog` module has the following methods:
   * `properties` String[] (optional) - Contains which features the dialog should use, can
     contain `openFile`, `openDirectory`, `multiSelections`, `createDirectory`
     and `showHiddenFiles`.
+  * `normalizeAccessKeys` Boolean (optional) - Normalize the keyboard access keys
+    across platforms. Default is `false`. Enabling this assumes `&` is used in
+    the button labels for the placement of the keyboard shortcut access key
+    and labels will be converted so they work correctly on each platform, `&`
+    characters are removed on macOS, converted to `_` on Linux, and left
+    untouched on Windows. For example, a button label of `Vie&w` will be
+    converted to `Vie_w` on Linux and `View` on macOS and can be selected
+    via `Alt-W` on Windows and Linux.
 * `callback` Function (optional)
   * `filePaths` String[] - An array of file paths chosen by the user
 

+ 27 - 0
lib/browser/api/dialog.js

@@ -38,6 +38,29 @@ const parseArgs = function (window, options, callback, ...args) {
   return [window, options, callback]
 }
 
+const normalizeAccessKey = (text) => {
+  if (typeof text !== 'string') return text
+
+  // macOS does not have access keys so remove single ampersands
+  // and replace double ampersands with a single ampersand
+  if (process.platform === 'darwin') {
+    return text.replace(/&(&?)/g, '$1')
+  }
+
+  // Linux uses a single underscore as an access key prefix so escape
+  // existing single underscores with a second underscore, replace double
+  // ampersands with a single ampersand, and replace a single ampersand with
+  // a single underscore
+  if (process.platform === 'linux') {
+    return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
+      if (after === '&') return after
+      return `_${after}`
+    })
+  }
+
+  return text
+}
+
 const checkAppInitialized = function () {
   if (!app.isReady()) {
     throw new Error('dialog module can only be used after app is ready')
@@ -171,6 +194,10 @@ module.exports = {
       throw new TypeError('Buttons must be an array')
     }
 
+    if (options.normalizeAccessKeys) {
+      buttons = buttons.map(normalizeAccessKey)
+    }
+
     if (title == null) {
       title = ''
     } else if (typeof title !== 'string') {