Add example for access keys in menus and feature detection (#390)

This commit is contained in:
Rob Wu
2019-01-04 16:40:05 -05:00
committed by wbamberg
parent 04ab5ab0e4
commit e37fd0510f
4 changed files with 137 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
# menu-accesskey-visible
Demonstrates access keys in the [menus API](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/menus/).
**This add-on uses the `menus` namespace to access the functions it needs to create menu items. Note that Chrome, Edge, and Opera all use the `contextMenus` namespace for this, so this extension will not work in these browsers. For compatibility with these browsers, Firefox also offers the `contextMenus` namespace, so to make this extension work with other browsers, use `contextMenus`.**
## What it does
This extension adds a menu item that has an access key.
An access key allows users to activate the menu item with one keystroke.
On Linux and Windows, the chosen access key is underlined.
On macOS, access keys are supported too, but without visual indicators.
When an access key is shared by multiple menu items, pressing the key
will switch between the menu items that share the access key. Otherwise
(if an access key is bound to one menu item only), the menu item is clicked.
The menu item in this demo logs a message to the extension's console upon
click. This console can be shown via the "Debug" button at `about:debugging` .
## What it shows
* Specifying access keys via `&` in the menu item title.
* Detecting feature support, exemplified by detecting support for the `visible`
property of the `menus.update` API that was also introduced in Firefox 63.
As access keys are only supported in Firefox 63 and later, this example also
shows how one can detect the feature support in the browser and fall back to
menu items without access keys if needed.

View File

@@ -0,0 +1,16 @@
{
"extensionName": {
"message": "Menu item with access key",
"description": "Name of the extension."
},
"extensionDescription": {
"message": "Demonstrates access keys in context menu items (if supported).",
"description": "Description of the add-on."
},
"menuItemWithAccessKey": {
"message": "Click &here && look at the extension's console",
"description": "Title of context menu item that logs a message on click. The letter after the first '&' is used as an access key. To show a single '&' in the menu, use '&&'."
}
}

View File

@@ -0,0 +1,71 @@
"use strict";
/**
* Performs feature detection, to detect whether access keys are supported.
*
* @returns {boolean}
* Whether access keys are supported in extension menu item labels.
*/
function detectAccessKeyMenuFeature() {
// Access keys are supported since Firefox 63:
// https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/63#Menus
//
// Before Firefox 63, any '&' in the menu label would appear literally. There
// is no direct way to detect whether access keys are supported, so we will
// indirectly detect support, via another feature that shipped in the same
// release: the 'visible' property in the menus API, as shown below.
// API parameters in the WebExtensions API are often validated immediately.
// If validation fails, an error is thrown.
// We can take advantage of this behavior to detect feature support:
// If a property is not supported, an error is thrown.
try {
// If the feature is supported, then the API will be invoked. Pass an unused
// menu item ID to make sure that we do not modify existing menu items.
browser.menus.update("Some ID that is not used by any existing menu item", {
visible: true,
});
return true;
} catch (e) {
return false;
}
// Side note: In Firefox 63, the menus.getTargetElement API was introduced.
// So the above try-catch could also have been replaced with this:
//
// return !!browser.menus.getTargetElement;
//
// The example uses try-catch anyway to demonstrate feature detection based
// on parameter properties.
}
var IS_ACCESS_KEY_SUPPORTED = detectAccessKeyMenuFeature();
function formatMenuLabel(menuLabel) {
if (!IS_ACCESS_KEY_SUPPORTED) {
// Access keys not supported (e.g. Firefox 62 and older).
// Remove ampersands to prevent them from showing up literally.
menuLabel = menuLabel.replace(/&(&?)/g, "$1");
}
return menuLabel;
}
// The "menuItemWithAccessKey" message is defined in _locales/en/messages.json
// and contains a '&' to specify an access key.
// To support Firefox 62 an earlier (where access keys were not recognized),
// the example below uses formatMenuLabel to post-process the message if
// access keys are not supported.
//
// If you are not interested in supporting Firefox 62 and earlier, remove all
// of the above code, and remove "formatMenuLabel(" and ")" below.
browser.menus.create({
id: "menu_item_with_access_key",
title: formatMenuLabel(browser.i18n.getMessage("menuItemWithAccessKey")),
contexts: ["page"]
});
browser.menus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "menu_item_with_access_key") {
console.log(`Clicked at ${info.pageUrl} in tab at index ${tab.index}`);
}
});

View File

@@ -0,0 +1,21 @@
{
"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.0",
"default_locale": "en",
"applications": {
"gecko": {
"strict_min_version": "56.0a1"
}
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"menus"
]
}