This documentation relates to the latest version of Confluence.
If you are using an earlier version, please go to the documentation home page and select the relevant version.

Web UI Plugins

All Versions
Click for all versions
Confluence 2.9 Documentation

Index

Web UI plugin modules are available in Confluence 2.2 and later.
Web UI plugin modules allow you to insert links, tabs and sections of links into the Confluence web interface. They're not much use on their own, but when combined with XWork-WebWork Plugins they become a powerful way to add functionality to Confluence.

Sections and Items

Web UI plugins can consist of two kinds of plugin modules:

  • web-item modules define links that are to be displayed in the UI at a particular location
  • web-section modules define a collection of links to be displayed together

Web items or web sections (referred to collectively as 'web fragments') may be displayed in a number of different ways, depending on the location of the fragment and the theme under which it is being displayed.

Locations

In a number of places in the Confluence UI, there are lists of links representing operations relevant to the content being viewed. These are the locations that you can customise:

Location key Themeable? Sectioned? Description Availability
system.admin The links in the left-hand menu on the global administrative console 2.2
system.space The tabs in 'Browse Space' 2.2
system.space.actions The action icons in the top-right of most space-related views 2.2
system.space.admin The links in the left-hand menu on the space administrative tab 2.2
system.space.pages The 'sub-tabs' in Browse Space → Pages 2.2
system.space.labels The 'sub-tabs' in Browse Space → Labels 2.2
system.space.advanced The links in the left-hand menu on the space advanced tab 2.2
system.content.add The menu items on the new add drop down menu available on spaces, pages and blogs. Sections: space, page. 2.8
system.content.action The menu items on the new tools drop down menu available on pages and blogs. Sections: primary, marker, secondary, modify. 2.8
system.comment.action The links on the bottom left of comments. Sections: primary, secondary. 2.8
system.labels The 'sub-tabs' in the global label view 2.2
system.user The menu items on the new user drop down menu available in the top bar of all pages. Sections: user-preferences, user-content, user-operations. 2.8
system.profile The tabs above the user profile 2.2
system.attachment Links on the right of the attachments list 2.8
system.profile.view The view user profile page. 2.9
  • Those locations marked as being 'themeable' can be moved around, reformatted or omitted by Theme Plugins. The descriptions above refer to where they are located in the default theme.
  • Locations marked as being 'sectioned' require that web items be grouped under web sections. In sectioned locations, web items that are not placed under a section will not be displayed.
  • It is possible for themes to make any themeable locations sectioned, even when the default theme doesn't. We do not recommend this, as it would mean any plugin taking advantage of this would only be compatible with a particular theme.
Theme Compatibility
Themes based on Confluence versions prior to 2.2 will continue to function with Confluence 2.2, but will not be able to display any custom Web UI fragments until they are updated.

Web Section Definition

You may choose to create your own web sections or add to Confluence's predefined ones (if it makes logical sense to). Here is a sample atlassian-plugin.xml fragment for a web-section:

<web-section key="page" name="Add Page Content" location="system.content.add" weight="200">
    <label key="page.word" />
</web-section>

This will create a new section on the Add Menu where you can add a new web-item. The location of this section depends on the relative weight compared to the other sections that have already been defined by Confluence (or other installed plugins).

The diagrams below illustrate the new web sections for the drop down menus.


Web sections for location system.content.action



Web sections for location system.content.add

Web Item Definition

Here's a sample atlassian-plugin.xml fragment for a web item:

<web-item key="spacelogo" name="Space Logo" section="system.space.admin/looknfeel" weight="40">
    <label key="configure.space.logo" />
    <link>/spaces/configurespacelogo.action?key=$helper.spaceKey</link>
    <icon height="16" width="16">
        <link>/images/icons/logo_add_16.gif</link>
    </icon>
    <condition class="com.atlassian.confluence.plugin.descriptor.web.conditions.NotPersonalSpaceCondition"/>
</web-item>
  • The key is the required plugin module key, which must be unique within the plugin. It is also used in the UI for determining which module is currently being displayed.
  • The name is a required displayable name for the module, only used in the plugin administrative UI
  • The section is the required location into which this web item should be placed. For non-sectioned locations, this is just the location key. For sectioned locations it is the location key, followed by a slash ('/'), and the name of the web section in which it should appear
  • The weight is required , and determines the order in which web items appear. Items are displayed top to bottom or left to right in order of ascending weight. (i.e. the 'lightest' weight is displayed first, the 'heaviest' weights sink to the bottom)
  • The label element is required, and is the i18n key that will be used to look up the textual representation and mouse-over text of the link.
  • The link element is required, and defines where the web item should link to. The contents of the link element will be rendered using Velocity, allowing you to put dynamic content in links. For more complex examples of links, see below.
  • The icon element is optional, and defines an icon to display with or as the link. Note: In some cases the icon element seems to be required. Try adding it if your web section is not displaying properly.
  • The condition element is optional, and defines a condition that must be satisfied for the web item to be displayed. If you want to 'invert' a condition, add an attribute 'invert="true"' to it. The web item will then be displayed if the condition returns false (not true).

Label elements

Label elements may contain optional parameters, as shown below:

<label key="navlink.attachments">
    <param name="param0">$!helper.page.title</param>
    <param name="param1">$!helper.numberOfAttachments</param>
</label>
  • The parameters allow you to insert values into the label using Java's MessageFormat syntax.
  • Parameter names must start with param and will be mapped in alphabetical order to the substitutions in the format string.
  • Parameter values are rendered using Velocity, allowing you to include dynamic content

Link elements

Link elements may contain additional information:

<link linkId="editPageLink" accessKey="$helper.action.getTextStrict('navlink.edit.accesskey')">/pages/editpage.action?pageId=$helper.page.id</link>
  • The linkId is optional, and provides an XML id for the link being generated.
  • The accessKey is optional and provides an access key for the link being generated. The contents of this element will be rendered using Velocity, allowing you to generate an access key dynamically.
    There is no standard way for Confluence to display a web item, so depending on where the item is being displayed, some information in the configuration may be ignored. For example themes may choose not to display the icon, or may choose to only display the icon. Similarly, the linkId and accessKey are only used in some locations.

Condition elements

Condition elements must contain a class attribute with the fully-qualified name of a Java class. The referenced class:

  • must extend com.atlassian.confluence.plugin.descriptor.web.conditions.BaseConfluenceCondition
  • must be able to be instantiated via a no-argument constructor
  • will be auto-wired by Spring before any condition checks are performed

For compatibility with Confluence 2.2 – 2.7, you should extend AbstractConfluenceCondition instead. However, this deprecated class will be removed in a future release.

Condition elements can take optional parameters. These parameters will be passed in to the Condition's init() method as a Map of String key/value pairs after autowiring, but before any condition checks are performed. For example:

<condition class="com.atlassian.confluence.plugin.descriptor.web.conditions.PagePermissionCondition">
    <param name="permission">edit</param>
</condition>

Multiple condition elements can be included in a single web item. If a web item contains multiple conditions, all conditions must be satisfied for the web item to be displayed.

To invert a condition, add the attribute 'invert="true"' to the condition element. This is useful where you want to show the section if a certain condition is not satisfied.

Web Section Definition

Here's a sample atlassian-plugin.xml for a web section:

<web-section key="mail" name="Mail" location="system.space.admin" weight="300">
    <label key="space-mail" />
    <condition class="com.atlassian.confluence.plugin.descriptor.web.conditions.NotPersonalSpaceCondition"/>
</web-section>
  • key, name, weight, label and condition are all the same as web-item
  • location is required, and serves the same purpose as section in web-item, except that a section can not be contained within another section.
  • Web sections do not have links or icons.

Q and A

How do I make use of sections or web items in my own themes?

Take a look at how they are used in the default themes, you should be able to get a good idea of the necessary code. For example, here is some sample code from space.vmd

#foreach ($item in $action.webInterfaceManager.getDisplayableItems("system.space", $action.remoteUser, $helper))
    <li><a href="$item.link.getDisplayableUrl($req, $helper)" #if ($context == $item.key) class="current" #end>
        $item.label.getDisplayableLabel($req, $helper)
    </a></li>
#end

Can I create new locations for web UI plugins in my own themes?

Yes. Just pick a new key for the location or section parameters of your plugin modules. By convention, you should probably use the standard 'inverted domain name' prefix so as not to clash with anyone else's plugins. We reserve all system.* locations for Confluence's core use.

Once again, however, we don't recommend this as you end up with plugins that are only useful in your own themes. Try to at least provide an alternative set of UI modules for people who are using other themes and still want to access the same functionality. You could, for example, define alternative UI plugin modules that placed your functions in Confluence's standard locations, but have a <condition> that disabled them in favour of your custom locations if your theme was installed.

If I create a Web Item that links to my custom action, how do I make it appear in the same tabs/context as the other items in that location?

The best way is to look at the .vm file of one of the existing items in that location. You are most interested in the #applyDecorator directive being called from that file. For example viewpage.vm, which defines the "View" tab in the system.page location has the following #applyDecorator directive:

#applyDecorator("root")
    #decoratorParam("helper" $action.helper)
    #decoratorParam("mode" "view")
    #decoratorParam("context" "page")

    <!-- some stuff... -->

#end

If you were writing a plugin that was destined to be added as another item in the page tabs, your Velocity file for that action would also have to have a similar decorator directive around it:

#applyDecorator("root")
    #decoratorParam("helper" $action.helper)
    #decoratorParam("mode" "myPluginKey")
    #decoratorParam("context" "page")

    <!-- some stuff... -->

#end

Note that you should put you Web Item's plugin key as the "mode". This way, Confluence will make sure that the correct tab is highlighted as the active tab when people are viewing your action.

In some cases, such as the browse space tabs, you may have to use "context" instead of "mode"

My Web UI link isn't appearing when I use the Adaptavist Theme Builder plugin - why?

Theme Builder uses completely customisable navigation and as such can't automatically display Web UI links because this would likely lead to duplication of many other, more common links.

You can, however use the {menulink} macro to insert any Web UI link using the following notation:

{menulink:webui|location=XXXX|key=YYYY}webui link{menulink}

Theme Builder 2.0.8 and above now supports a growing number of third party plugins as standard - for more information see the online documentation. If you have a publicly available plugin and want an inbuilt menulink locaiton for it, please contact Adaptavist.

The breadcrumb trail for my web ui administration/space administration/tab plugin is showing the class name - how do I fix it?

atlassian-plugin.xml
<!--Make sure each name is unique-->
         <resource type="i18n" name="i18n-viewreview"
  location="resources/ViewReviewAction" />
In the java
//in an action
  I18NBean i18NBean = getI18n();

  //or in a macro or other sort of plugin
   ThemeHelper helper = this.getHelper();
                 ConfluenceActionSupport action = (ConfluenceActionSupport) helper.getAction();
                 Locale locale = action.getLocale();
                 I18NBean i18nBean = i18NBeanFactory.getI18NBean(locale);

  //and
     public void setI18NBeanFactory(I18NBeanFactory i18NBeanFactory)
     {
         this.i18NBeanFactory = i18NBeanFactory;
     }
Use a normal properties file

re: where the properties file goes

If we're talking about actions: the properties file with the same name as the relevant action can go in the same directory as the action: So, if you had XYZAction.java, then XYZAction.properties could live in the same directory. And you would not have to do anything in the atlassian-plugin.xml file.

If you don't want it to live there, or if you're not talking about an action, then you define a resource in the atlassian-plugin.xml and tell it to live whereever you want, the standard appears to be resources. In the source it would be etc/resources. In the jar it would be resources/

The property that handles the breadcrumb has to be the fully qualified name of the class plus .action.name

So, for the SharePointAdmin property I used: com.atlassian.confluence.extra.sharepoint.SharePointAdmin.action.name=SharePoint Admin

Labels:

webui webui Delete
links links Delete
plugin plugin Delete
builder builder Delete
Enter labels to add to this page:
Wait Image 
Looking for a label? Just start typing.
  1. Apr 30, 2006

    Dan Hardiker says:

    The label element is required, and is the i18n key that will be used to look up ...

    The label element is required, and is the i18n key that will be used to look up the textual representation and mouse-over text of the link.

    If I add a menu item to the admin menu (through the system.admin key), and I give it the label key of "myPlugin.link.text" ... how do I provide a value for it? If I want to have the text resolve into multiple languages, can I do that too?

    1. Apr 30, 2006

      Mike Cannon-Brookes says:

      Mate - the value is simply provided in the i18n properties files with your plugi...

      Mate - the value is simply provided in the i18n properties files with your plugin. Bundled as a <resource> type="i18n" from memory.

      1. May 01, 2006

        Dan Hardiker says:

        A ha! An example of this can be seen on the Report Plugin Module page ... a cle...

        A ha!

        An example of this can be seen on the Report Plugin Module page ... a clearer example of i18n in plugins may be worth while for newbies, as even I had trouble figuring out what goes where. (Granted, I've not worked with any i18n implementation that I hadn't written myself though.)

        1. Nov 10, 2006

          Laura Kolker says:

          FYI: Looks like web ui plugin + resources don't work in 2.2 http://jira.atlassi...

          FYI: Looks like web ui plugin + resources don't work in 2.2

          http://jira.atlassian.com/browse/CONF-6317

          (Just a reference, as I spent way too much time poking at this.)

  2. Apr 30, 2006

    Dan Hardiker says:

    The above tells me lists the various areas I can link into (system.admin for exa...

    The above tells me lists the various areas I can link into (system.admin for example) but doesnt list the sections available ... there is only one in your example which is system.space.admin/looknfeel but doesn't list which others there are.

    1. Apr 30, 2006

      Dan Hardiker says:

      For reference, you can find the built in sections available in confluence-2.2-so...

      For reference, you can find the built in sections available in confluence-2.2-source/confluence/src/etc/java/plugins if you have source access, or confluence-2.2/confluence/WEBINF/classes/plugins if you have the dist. They are listed in the *-sections.xml files.

  3. May 09, 2006

    Michelle A. Hoyle says:

    So can I use this to replace the nasty hard-coded additions I had to make to con...

    So can I use this to replace the nasty hard-coded additions I had to make to confluence/template/includes/macros.vm? Every time I upgrade Confluence, I have to go back and manually reapply the following changes:

    1) #macro (usernameLink $username): This is used to modify the usernameLink to include a clickable icon which takes you to the person's Guild Profile page in addition to the standard (and, for our purposes, mostly useless) Confluence user profile page.

    Original Code
    #macro (usernameLink $username)
    #if ($username != "")
        #if ($action.getUserFullName($username))
            <a href="$!req.contextPath/display/~$generalUtil.
            doubleUrlEncode($username)">
            $action.getUserFullName($username)</a>
        #else
    Changed Code
    #macro (usernameLink $username)
    #if ($username != "")
        #if ($action.getUserFullName($username))
            <a href="$!req.contextPath/display/PROFILE/
            $generalUtil.doubleUrlEncode($action.
            getUserFullName($username))" 
            title="Visit $action.getUserFullName($username)'s 
            Guild Profile page">
            <img src="$req.contextPath/images
            /icons/droplet_16.png" 
            height="16" width="16" 
            border="0" align="middle" alt="" /></a>
           <a href="$!req.contextPath/display/~$generalUtil.
           doubleUrlEncode($username)" 
           title="View $action.getUserFullName($username)'s 
           Confluence profile">
           $action.getUserFullName($username)</a>
        #else

    2) usernavbar: added code to include guild profile page edit droplet and link to Java chat applet page.

    Original Code
    <a href="$req.contextPath/display/~$generalUtil.
    doubleUrlEncode($user.name)">Profile</a> |
    Changed Code
    <a href="$req.contextPath/display/PROFILE/$generalUtil.
    doubleUrlEncode($user.fullName)" title="Visit your Guild Profile 
    page"><img src="$req.contextPath/images/icons/droplet_16.png" 
    height="16" width="16" border="0" align="absmiddle" alt="" 
    style="margin: 0 3px 0 0;" class="none" /></a><a 
    href="$req.contextPath/display/~$generalUtil.
    doubleUrlEncode($user.name)">Profile</a> | 
    <a href="http://www.wowkindness.com/cgi-bin/chat/index.php?nick=
    $generalUtil.doubleUrlEncode($user.fullName)" title="Multi-Chat">Chat</a> |

    3) usernavbar: Added code to put inactive "Chat" link into nav bar when not logged in.

    Original Code
    <a href="$seraph.getLinkLoginURL($req)">Log In</a>
    Changed Code
    Chat |
                <a href="$seraph.getLinkLoginURL($req)">Log In</a>

    It's a pain in the butt but I didn't see an easy way around it previously. Will this new UI plugin help at all?

    1. May 09, 2006

      Jonathan Nolen says:

      Yep! This is exactly the usecase we built this feature for. It should do the tri...

      Yep! This is exactly the usecase we built this feature for. It should do the trick.

      Cheers,
      Jonathan

  4. Nov 16, 2006

    Laura Kolker says:

    Quote from above: Note that you should put you Web Item's plugin key as the "mod...

    Quote from above:

    Note that you should put you Web Item's plugin key as the "mode". This way, Confluence will make sure that the correct tab is highlighted as the active tab when people are viewing your action. In some cases, such as the browse space tabs, you may have to use "context" instead of "mode"

    I've found if I'm creating a new space tab, that I run into some difficulties here.
    If I don't make the context equal to "space", then the tabs don't show.
    But the space decorator (space.vmd) shows that it's the context == plugin.key that determines which tab is highlighted:

    ## line 29 in space.vmd
    <li><a href="$item.link.getDisplayableUrl($req, $helper)" #if ($context == $item.key)
     class="current" #end>$item.label.getDisplayableLabel($req, $helper)</a></li>

    Just for thoroughness, I checked setting the mode to my plugin key, and that appears to have no effect.

    I've found the following JIRA issue,
    http://jira.atlassian.com/browse/CONF-6853

    which seems related, but no one's responded to Dan Hardiker's request for clarification on whether related space issues have been resolved.

    In the meantime, I've got a work-around, which is more than a bit of kludge, but it'll do until I hear of a better solution.

    //add this in the body of your velocity file
            <script type="text/javascript">
               function fixTab() {
                 var tablist = document.getElementById('foldertab');
                 for (var i = 0; i < tablist.childNodes.length; i++) {
                    var liElement = tablist.childNodes[i];
                    if (liElement.childNodes[0] == null) {
                       continue;
                    }
                    if (liElement.childNodes[0].href.match("something.unique.in.my.action.name")) {
                       liElement.childNodes[0].className = "current";
                       
                    }
                 }
               }
               fixTab();
            </script>
    1. Nov 16, 2006

      Laura Kolker says:

      I just thought of a better solution: root.vmd shows the following #elseif ($c...

      I just thought of a better solution:

      root.vmd shows the following

      #elseif ($context.startsWith("space-"))           
      ## Space tabs (Friday afternoon hack)
            #applyInlineDecorator("space" $body $params)

      So, all you have to do is make the plugin key start with space- (and still be unique, and then when you make the context equal to, the highlighting works correctly.

      1. Dec 08, 2006

        Jean Marois says:

        I have a similiar issue with tabs added to the User Profile, but can't use the "...

        I have a similiar issue with tabs added to the User Profile, but can't use the "simpler" hack, so I used a modified version of your previous solution:

        <script type="text/javascript">
                   function fixTab() {
                     var tablist = document.getElementById('foldertab');
                     for (var i = 0; i < tablist.childNodes.length; i++) {
                        var liElement = tablist.childNodes[i];
                        if (liElement.childNodes[0] == null) {
                           continue;
                        }
                        if (liElement.childNodes[0].href.match("/path/to/myplugin.action*")) {
                           liElement.childNodes[0].className = "current";
                        }
                        else { 
                           liElement.childNodes[0].className = "";
                        }
                     }
                   }
                   fixTab();
        </script>

        I added the else statement to make sure no other tab is set as the current.

        1. Dec 08, 2006

          Jean Marois says:

          I forgot to explain why I need to unset the current tab. The global.vm will not ...

          I forgot to explain why I need to unset the current tab. The global.vm will not display your page unless you set your decorator mode parameter to one of the existing tabs, i.e. view-profile, edit-profile, ... There is no else block in the profile context section.

          #elseif ($context == "profile")
          ...
                              ##MODE - VIEW-PROFILE
                              #if ($mode == "view-profile")
          ...
                              ##MODE - EDIT-PROFILE || CHANGE-PASSWORD-PROFILE
                              #elseif ($mode == "edit-profile" || $mode == "change-password-profile")
          ...
                              #elseif ($mode == "configure-rss-feed" || $mode == "my-labels" || $mode == "edit-notifications-profile")
          ...
                              #elseif ($mode == 'drafts')
          
          ...
                              #end
                    #elseif ($context == "labels")
          ...
  5. Feb 16, 2007

    Laura Kolker says:

    Condition elements must contain a class attribute with the fully-qualified name...

    Condition elements must contain a class attribute with the fully-qualified name of a Java class. The referenced class:
    must implement com.atlassian.confluence.plugin.descriptor.web.Condition

    This appears to be out of date as of Confluence 2.3.
    Anyone know what the new class is?

    Thanks
    Laura

    1. Feb 17, 2007

      Jean Marois says:

      I believe its actually been com.atlassian.confluence.plugin.descriptor.web.condi...

      I believe its actually been com.atlassian.confluence.plugin.descriptor.web.conditions.AbstractConfluenceCondition since at least 2.2.9.

      Jean

      1. Feb 19, 2007

        Laura Kolker says:

        Hi Jean, Thanks for the tip. re: 2.2.9 Interesting. The Condition class was,...

        Hi Jean,

        Thanks for the tip.

        re: 2.2.9

        Interesting. The Condition class was, however, still usable in 2.2.9
        Perhaps it was deprecated at that time?

        Laura

  6. Aug 31, 2007

    Anonymous says:

    For the record, the linked actions Classes must implement either SpaceAware or P...

    For the record, the linked actions Classes must implement either SpaceAware or PageAware so they are properly decorated...

    Regards,

    robertowhospentwaytoomanyhourstofigurethisout

  7. Apr 14

    Roberto Dominguez says:

    Err, what happened with system.page.actions web items, as per Web UI Plugins? Ar...

    Err, what happened with system.page.actions web items, as per Web UI Plugins? Are they getting ignored?

  8. Sep 01

    Shannon Krebs says:

    It looks like the system.user location doesn't work in confluence 2.8 as claimed...

    It looks like the system.user location doesn't work in confluence 2.8 as claimed. I'm guessing this is because it only became sectioned in 2.9, thus it doesn't understand the sectioned web item that is working in 2.9... ?

    It would be good to add a screenshot of the sections for the user menu as well.

    1. Sep 08

      Ming Giet Chong says:

      Hi Shannon, I have done quick try at my side and the system.user location key i...

      Hi Shannon,

      I have done quick try at my side and the system.user location key is working fine in Confluence 2.8 and 2.9. You should be able to see the new tab added to the user drop down menu for each page.

      For development query, I would suggest you to join the Confluence developer forum for further discussion:

      Regards,
      MG