Blogs

12 min read

Custom Macro Parameters with JavaScript

Mar 12, 2018 11:00:00 AM

Introduction 

Custom macros are a popular, supported, and versatile addition to any confluence page. Confluence users are able to use macros by making their own, searching the macro library, or by getting access to additional macros through add-ons. If you are making your own macro through an add-on, you will know that the parameter types, aka fields, are limited to the following: 

    • boolean - displays a check box.
    • enum - displays a select field.
    • string - displays an input field (this is the default if unknown type).
    • spacekey - displays an autocomplete field for search on space names.
    • attachment - displays an autocomplete field for search on attachment filenames.
    • username - displays an autocomplete field for search on username and full name.
    • confluence-content - displays an autocomplete field for search on page and blog titles.

Using JavaScript and Soy templates, you are able to inject custom parameters into a macro. The following tutorial is an example of a custom field injected into a basic macro form. The goal is to create a multi-select drop down menu comprised of static predetermined menu items. Note- JS functionality to create a multi-select list and the CSS are not included. 

 

Steps for injecting an element into a macro 

Building the macro

Example code of plugin.xml 

<xhtml-macro name="macro-list" key="macro-list" class="your.class.name"  documentation-url="#"
             icon="/path/to/yourPic.jpg">
    <category name="external-content"/>
    <parameters>
        <parameter name="User" type="username"/>
        <parameter name="Page" type="confluence-content"/>
        <parameter name="StatusSelect" type="string"/>
        <parameter name="Status" type="string"/>
        <parameter name="Width" type="percentage" default="100%"/>
        <parameter name="Max Results" type="int" default="30"/>
    </parameters>
</xhtml-macro>

 

Macro prior to injecting content

*Note: The "Status" parameter is not visible in this image. That is because the element is hidden with CSS. More on why the element is hidden in the JavaScript section. 

 

Configuring the Soy template multi-select code

{template .multiSelect}
    <div class="status-container">
        <div class="closed-status-margin status-selected-container macro-input-fields text">
            <span class="aui-icon aui-icon-small aui-iconfont-arrow-down select-icon" onclick="toggleStatuses()"></span>
        </div>
        <ul class="status-list hide-statuses">
            <li value="created" onclick="statusSelect(this)">Created</li>
            <li value="deleted" onclick="statusSelect(this)">Deleted</li>
            <li value="sent" onclick="statusSelect(this)">Sent</li>
            <li value="correct" onclick="statusSelect(this)">Correct</li>
        </ul>
    </div>
{/template}


JavaScript injection

JS code with explanation

//Run function on ajaxComplete to capture edit macro view.
$(document).ajaxComplete(function() {
    //looking for the macro-list macro to start running
    if( AJS.$("table[data-macro-name = 'macro-list']")){
            //must verify that the MacroBrowser is available to prevent errors
            if (AJS.MacroBrowser) {
            //override command that selectes the ds macro and the field/s selected
            AJS.MacroBrowser.setMacroJsOverride("macro-list", {
                fields: {
                    //calls anonymous function on string fields
                    "string": function (param) {
                        //checks specifically for the string input we want to inject to
                        if (param.name == "StatusSelect") {
                            //calls our function with the input's selected string param
                            return handleSpacesLookup(param);
                        }
                    }
                }
            });
        }
    }
});
//globally available but only called if the above criteria is met
function handleSpacesLookup() {
    //grabbing the div that surrounds our selected input/param
    var paramDiv = AJS.$(Confluence.Templates.MacroBrowser.macroParameterSelect());
     
    //create a variable for our desired template
    var docStatus = path.to.your.template.multiSelect();
     
    //setting a variable to the paramDiv that corresponds to our desired input area via ID
    var select = AJS.$("#macro-param-div-StatusSelect", paramDiv);
     
    //adding our docStatus element to the selected div
    paramDiv.append(docStatus);
 
    //return the selected/created element to the macro
    return AJS.MacroBrowser.Field(paramDiv, select);
};
  
//Functional logic for the multiselect not included.
 

Completed front-end example with JavaScript

Why is the Status Parameter Gone? 

The drop down multi-select captures the user's selection on the front end. When passing the macro form information back to the server via the preview or the save button, the Status Select format is not readable. To make sure that your information is able to be parsed, you may insert relevant information into another macro field. In this case, the user's responses are sent to the hidden Status parameter each time he/she makes a change to the StatusSelect. On save or on preview, only the hidden information is sent to be parsed. 

 

Potential Issues 

  • I only see an empty field when opening the edit macro, I can only see my field when reloading the page with the editable macro, OR I am getting null variable errors. 

    This may be a JS async error, which could explain some inconsistencies. Make sure that this JS file is accessible to the page, that functions are properly nested, and that the initial if clause is triggered as expected. The edit screen and dialog boxes are not connected to a page reload so queries done "on load" of the page will not be caught at this point. Use .ajaxComplete or an event trigger to re-run necessary functions. 

  • My new element works but now I am missing functionality from other parts of my page.

    Make sure that your selectors are unique and as specific as possible. Try to limit using css and JS selectors by the AUI class names as these are repeated through out Confluence. 

  • I am appending my element but only see a blank input box. 

    Your parameter type may limit the content that can be appended to it. For example, select lists cannot have non-option items added to it and will instead render a broken input box. Confirm that your template has the appropriate wrappers if any. You may need to append your template to the container instead of the parameter. 

Webinars

Case Studies

Blog