Dynamic flyout menus in uxp plugins for InDesign

By ‘dynamic’ I mean a menu that contains menu items that can be checked/unchecked, enabled/disabled, removed/added while the plugin is running, etc.

If you don’t need any of those things, then the recipe in the documentation shows you how to set up your menu and capture when the user invokes a menu item. The recipe is written for a vanilla javascript setup. If you are using react, @SweatersInSummer has worked out how to set it up, see here: http://forums.creativeclouddeveloper.com/t/uxp-flyout-menu-manifest-error/8576/13.

If, as I do, you want the dynamic features, I am sharing a method for doing it. I have written a simple (silly) proof-of-concept plugin. Here is a screen recording:

All of this applies to uxp plugins in InDesign, not to plugins in Photoshop. Flyout menus have been available in Photoshop for a long time, but are only available in InDesign with the latest (v20) release. @DavideBarranca has shown how to do dynamic features in flyout menus in Photoshop in his book https://www.ps-scripting.com/uxp-react.html and here: https://www.youtube.com/watch?v=v-x1ZrOtlzQ.

Evidently, the way the flyout menus have been implemented in the two programs is different because code that works in Photoshop does not in InDesign. In the UXP documentation for InDesign there is information about the class UxpMenuItem which suggests you can simply set the checked or enabled property of a menu item, but, as far as I can tell, this does not work.

The approach that I have taken essentially entails addressing the menu not from the uxp/panel side, i.e. not as a collection of uxpMenuItems, but from the InDesign side, i.e. as an InDesign menu which, like any other, can contain submenus, menuSeparators and menuItems that can be backed by scriptMenuActions.

A uxp plugin in InDesign ‘under-the-hood’ creates an InDesign menu. When the user clicks on the flyout button/icon it is this menu that they see. (I wrote about this, including a warning, in this thread: http://forums.creativeclouddeveloper.com/t/how-uxp-flyout-menus-have-been-implemented-in-indesign/8558.) Addressing this menu directly gives you full control over it.

The only code I have on the uxp/plugin side is this (in the entrypoints.setup() function for the panel):

			menuItems: [
				{id:'separator', label:'-'}
			],

Defining an array containing a single menu separator is enough to trigger the creation of the InDesign menu (sadly, defining an empty array does not).

The InDesign menu created by the plugin is named by the label (yes, label) that you give to your panel. My demo panel has the label ‘Cricketers’, so I address the menu like this:

const flyoutMenu = app.menus.itemByName('Cricketers');

I create the menu in the create lifecycle hook of the plugin and destroy it in the destroy lifecycle hook. While the plugin is running, I can manipulate it in any way I like, as you can see.

I am attaching the plugin for anyone who is minded to poke around in the code. I have commented the code to explain what I’m doing and included in the comments just a few minor things to watch out for.

com.wherebysoftware.cricketers.flyout_ID.ccx (5.1 KB)

Philip

4 Likes