With Photoshop CC 2014.2 (implementing CEP 5.2) it’s finally possible to have flyout menus in HTML Panels too - as we had back in Flash land. This Tip shows you how to set them and deal with their click handler.
The full code of this demo extension is available on my GitHub page in the PS Panels Boilerplate project. Things are pretty simple, though: you first set an XML String which describes the menu:
var flyoutXML = '\
<Menu> \
<MenuItem Id="enabledMenuItem" Label="Enabled Menu Item" Enabled="true" Checked="false"/> \
<MenuItem Id="disabledMenuItem" Label="Disabled Menu Item" Enabled="false" Checked="false"/> \
\
<MenuItem Label="---" /> \
\
<MenuItem Id="checkableMenuItem" Label="Checkable Menu Item" Enabled="true" Checked="true"/> \
\
<MenuItem Label="---" /> \
\
<MenuItem Id="actionMenuItem" Label="Click me to enable/disable the Target Menu!" Enabled="true" Checked="false"/> \
<MenuItem Id="targetMenuItem" Label="Target Menu Item" Enabled="true" Checked="false"/> \
\
<MenuItem Label="---" /> \
\
<MenuItem Label="Parent Menu (wont work on PS CC 2014.2.0)"> \
<MenuItem Label="Child Menu 1"/> \
<MenuItem Label="Child Menu 2"/> \
</MenuItem> \
</Menu>';
Remember the \
at the lines’ end to escape the carriage return. Nothing fancy, just MenuItem
tags to define the structure. Mind you, nested menus don’t work right now (in Photoshop CC 2014.2.0 - although After Effects and Premiere are OK) but the bug is going to be fixed. You actually build the menu feeding setPanelFlyoutMenu
with the XML string:
// Uses the XML string to build the menu
csInterface.setPanelFlyoutMenu(flyoutXML);
An event listener has been added to respond to clicks (the event is "com.adobe.csxs.events.flyoutMenuClicked"
):
csInterface.addEventListener("com.adobe.csxs.events.flyoutMenuClicked", flyoutMenuClickedHandler);
When a click occurs, an event
is passed to the callback. It’s data
attribute is an object containing both menuId
and menuName
. The callback in my case is as follows:
// Ugly workaround to keep track of "checked" and "enabled" statuses
var checkableMenuItem_isChecked = true;
var targetMenuItem_isEnabled = true;
// Flyout Menu Click Callback
function flyoutMenuClickedHandler(event) {
// the event's "data" attribute is an object, which contains "menuId" and "menuName"
console.dir(event);
switch (event.data.menuId) {
case "checkableMenuItem":
checkableMenuItem_isChecked = !checkableMenuItem_isChecked;
csInterface.updatePanelMenuItem("Checkable Menu Item", true, checkableMenuItem_isChecked);
break;
case "actionMenuItem":
targetMenuItem_isEnabled = !targetMenuItem_isEnabled;
csInterface.updatePanelMenuItem("Target Menu Item", targetMenuItem_isEnabled, false);
break;
default:
console.log(event.data.menuName + " clicked!");
}
csInterface.evalScript("alert('Clicked!\\n \"" + event.data.menuName + "\"');");
}
The code above:
- fires a simple alert with the Label when a menu item is clicked;
- lets you check/uncheck a menu item;
- toggles the enabled/disabled status of a menu item when you click on a different item.
I haven’t been able to retrieve the enabled/disabled and checked/unchecked menu items status dynamically, so I’ve worked around storing them in vars. Not ideal maybe, but it works As you see, I’ve used the updatePanelMenuItem
function, which is used this way (straight from CSInterface.js
sourcecode):
/**
* Updates a menu item in the extension window's flyout menu, by setting the enabled
* and selection status.
*
* Since 5.2.0
*
* @param menuItemLabel The menu item label.
* @param enabled True to enable the item, false to disable it (gray it out).
* @param checked True to select the item, false to deselect it.
*
* @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false).
* Fails silently if menu label is invalid.
*
* @see HostCapabilities.EXTENDED_PANEL_MENU
*/
CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) {
var ret = false;
if (this.getHostCapabilities().EXTENDED_PANEL_MENU) {
var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked);
ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus));
}
return ret;
};
That’s it, hope this helps! The extension is available on GitHub in my PS Panels Boilerplate project.
The Photoshop HTML Panels Development Course

If you’re reading here, you might be interested in my Photoshop Panels development – so let me inform you that I’ve authored a full course:
- 300 pages PDF
- 3 hours of HD screencasts
- 28 custom Panels with commented code
Check it out! Please help me spread the news – I’ll be able to keep producing more exclusive content on this blog. Thank you!