Why is Why is AJS.Confluence.PropertyPanel.Macro undefined?

I noticed that a custom macro editor broke in one of my Confluence Server/DC plugins.

We were using AJS.Confluence.PropertyPanel.Macro.registerButtonHandler to wire up events for macro editor buttons that are defined in a property-panel in our macro definition in atlassian-plugin.xml.

Like this:
AJS.Confluence.PropertyPanel.Macro.registerButtonHandler('MyButton', function(e, macroNode) {...});

and that caused:
TypeError: Cannot read properties of undefined (reading ‘registerButtonHandler’)
(but it worked for quite some time before this)

We found a hint about another approach so we are now doing that and it works:

  AJS.bind('add-handler.property-panel', function(event, panel) {
    panel.registerButtonHandler('MyButton', function(e, macroNode) {

I don’t see any mention of the AJS.Confluence.PropertyPanel.Macro API/object going away so I don’t know if it went away or if something changed in the ecosystem to break my usage of it?

I’d like to understand more about why my implementation broke and why the different approach works. Not sure exactly when it broke. The fix works on Confluence 7.13 and Confluence 8.3.

Any hints appreciated.


1 Like

As it turns out, in recent versions of Confluence, adding event wiring for add-handler.property-panel breaks the native Confluence attachment editor. In page edit mode, the editor for attached images does not render when you click on the image (if you try to use your own event handling for ‘add-handler.property-panel’)

AJS.bind('add-handler.property-panel', function(event, panel) {
    panel.registerButtonHandler('MyButton', function(e, macroNode) {

I think that, maybe, the original problem is that Confluence has added a panel that does not have a registerButtonHandler function on it. In the old days all of the property panels that were rendered on a page had a registerButtonHandler function on them.

In more recent versions of Confluence I think a page editor is rendered with some property panels that do not have a registerButtonHandler function on it. When your custom property panel event wiring code tries to use registerButtonHandler when that panel is rendered it explodes your custom panel event wiring code.

I have added a check like “if (panel.registerButtonHandler) {…}” and that might be working without interfering with other property panel editors in the page editor (like the image size editor)

Were you able to replicate the problem of having the Macro object undefined?
I applied the same solution by checking if the Macro object exists, but this only prevents the error. It doesn’t make the button handler to work.

Hello @PauloAlves ,
Yes my button event handler code is working in the presence of null “panel” objects being passed to the “add-handler.property-panel” event handler in AJS.bind(…) calls.

The null “panel” objects are the ones we don’t care about if we are wiring up events for “property-panel” buttons in macro editors. We filter those ones out.

This is a specific use-case. It only applies to custom buttons added to your macro editor via a <property-panel> element for your <xhtml-macro> element in atlassian-plugin.xml.

Those custom buttons are passed as non-null “panel” args to the “add-handler.property-panel” event handler and we want to wire up our custom event handler to them.

In my use-case I am wanting to filter out the null “panel” objects because they are from a change that Confluence made to its rendering of buttons in their page attachments editor. That editor used to result in a non-null “panel” arg being passed to ‘add-handler.property-panel’ event handlers but now passes null.

Confluence/Atlassian refactored that editor’s event code without realizing it breaks their recommended approach for property-panel event wiring. An obscure corner-case for sure, but it is a regression and requires a null/undefined check for the specific use case of property-panel event button event wiring. Maybe it is a best practice to check for null/undefined anyways, so this really is an obscure corner-case with an easy fix. The hard part is figuring out why the wiring is broken and what to do about it… but that is done (I think).