Working with Flags
Flags allow you to simplify switching logic and improve performance within your themes. A flag is a named register that stores one of the following states:
True - The flag is set
False - The flag is not set
If you use a flag that hasn’t been defined, it’s treated as having a false state. Several macros are flag-aware, allowing you to toggle them on or off based on the state of one or more flags. You can also use flags to toggle the effect of parts of your CSS style sheets.
Flags also apply flag-FLAGNAME
classes to the body element of the theme so they can be used for triggering CSS customizations. Flags can be set against various targets, each of which has a different level of persistence.
See the following for more information:
How to Set a Flag
To set, and subsequently unset, a flag, you use the Set Flag macro. For example, the following markup will set a flag called foo, and then un-set it:
Storage Format
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">foo</ac:parameter>
</ac:macro>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">foo</ac:parameter>
<ac:parameter ac:name="state">false</ac:parameter>
</ac:macro>
Wiki Markup
{set-flag:foo}
{set-flag:foo|state=false}
You can set flags in a wiki page or in a theme panel. In most cases, you’ll want to conditionally set a flag based on some other criteria. For example:
Storage Format
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="title">Forum</ac:parameter>
<ac:parameter ac:name="recurse">true</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">in-the-forum</ac:parameter>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
Wiki Markup
{panel-show:title=Forum|recurse=true}
{set-flag:in-the-forum}
{panel-show}
The markup above would set the in-the-forum
flag only when the user is looking at a page called Forum or any of its child pages due to the recurse=true
.
The macros most commonly used to set and unset flags in this manner are as follows:
- Panel Show macro
- Panel Hide macro
- Bubbles Show macro
- Bubbles Hide macro
These show/hide macros will show or hide their contents based on the parameters you set, allowing you to determine when the Set Flag macro is triggered to set or unset a flag.
How to Unset a Flag
As shown below, to unset or clear a flag, set its state to false.
Storage Format
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">in-the-forum</ac:parameter>
<ac:parameter ac:name="state">false</ac:parameter>
</ac:macro>
Wiki Markup
{set-flag:in-the-forum|state=false}
You can also completely remove a flag by setting the state to remove:
Storage Format
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">in-the-forum</ac:parameter>
<ac:parameter ac:name="state">remove</ac:parameter>
</ac:macro>
Wiki Markup
{set-flag:in-the-forum|state=remove}
What to do with Flags
You can use flags to toggle the rendering of other macros and wiki markup. For example, using our in-the-forum
flag above, we can now show some extra content in a theme sidebar when that flag is set to the following:
Storage Format
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="flag">in-the-forum,foo</ac:parameter>
<ac:rich-text-body>
this stuff will only be shown when either the 'in-the-forum' and/or 'foo' flag has been set
</ac:rich-text-body>
</ac:macro>
Wiki Markup
{panel-show:flag=in-the-forum,foo}
this stuff will only be shown when either the 'in-the-forum' and/or 'foo' flag has been set
{panel-show}
Or we could show some content when the flag is not set, like the markup as follows:
Storage Format
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="notflag">in-the-forum,foo</ac:parameter>
<ac:rich-text-body>
this stuff will only be shown if neither the 'in-the-forum' and 'foo' flags have been set
(in other words, if the 'in-the-forum' or 'foo' flags are set, ths won't be shown)
</ac:rich-text-body>
</ac:macro>
<ac:macro ac:name="panel-hide">
<ac:parameter ac:name="flag">in-the-forum,foo</ac:parameter>
<ac:rich-text-body>
this is does the same as the panel-show markup shown above, we've changed 'notflag' to 'flag'
so it gets hidden when either of the flags are set
</ac:rich-text-body>
</ac:macro>
Wiki Markup
{panel-show:notflag=in-the-forum,foo}
this stuff will only be shown if neither the 'in-the-forum' and 'foo' flags have been set
(in other words, if the 'in-the-forum' or 'foo' flags are set, ths won't be shown)
{panel-show}
{panel-hide:flag=in-the-forum,foo}
this is does the same as the panel-show markup shown above, we've changed 'notflag' to 'flag'
so it gets hidden when either of the flags are set
{panel-hide}
Macros that Support Flags
All ThemeBuilder macros support flags from Confluence 5 onwards.
The flag parameters are as follows: * flag – defines which flags must be set for the macro to be processed * notflag – determines which flags must not be set for the macro to be processed.
When to Use Flags
Flags become useful in more complex theme customizations because they allow you to separate a lot of the logic that determines what should be displayed to the end-user. We’ll cover some use cases below.
Setting defaults
There are many cases where you’ll want to set a default state and override it with a known state based on various criteria. If none of the known states are found, you’ll be left with the default state.
A simple example is determining whether a user is logged in or not, and whether they are a member of staff:
Storage Format
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">anonymous-user</ac:parameter>
</ac:macro>
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="group">confluence-users</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">anonymous-user</ac:parameter>
<ac:parameter ac:name="clear">true</ac:parameter>
</ac:macro>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">registered-user</ac:parameter>
</ac:macro>
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="group">staff-group</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">staff-user</ac:parameter>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
Wiki Markup
{set-flag:anonymous-user}
{panel-show:group=confluence-users}
{set-flag:anonymous-user|clear=true}
{set-flag:registered-user}
{panel-show:group=staff-group}
{set-flag:staff-user}
{panel-show}
{panel-show}
The result is explained below:
If the user is not logged in, only the
anonymous-user
flag will be set (the default state).If the user is logged in, the
anonymous-user
flag will be un-set (cleared), and theregistered-user
flag will be setIf the user is logged in and is also a member of your staff-group, the
staff-user
flag will be set in addition to theregistered-user
flag.
Flags should never be treated as a security mechanism.
In the example above, a user could set a staff-user
flag from a wiki page. You could override any flags set by users by defining some more defaults at the start of your flag logic. For an example, look at the markup included here:
Storage Format
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">registered-user</ac:parameter>
<ac:parameter ac:name="state">false</ac:parameter>
</ac:macro>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">staff-user</ac:parameter>
<ac:parameter ac:name="state">false</ac:parameter>
</ac:macro>
Wiki Markup
{set-flag:registered-user|state=false}
{set-flag:staff-user|state=false}
Improved Performance
Often, a state is used several times in a theme layout. Although lots of caching is used in Builder and Confluence, if you’re repeatedly checking for a specific state (particularly complex states based on several criteria), it can degrade performance and make your theme configuration messy.
A common scenario in themes we’ve developed for customers is choosing to show an edit button and other links related to page editing or not. The general logic runs along these lines:
Don’t show the edit features on top-level pages, or the home page
Only show edit features if the user is logged in—regardless of permissions for anonymous users
Only show edit features in the Documentation area of a space if the user is a member of the staff
Quite a few things need to be checked to confirm whether the edit features should be shown, and in many cases, the outcome will be performed in several locations and across multiple theme panels. This is an ideal use case for flags.
Based on the flags set by earlier examples, the logic to do this would be:
Storage Format
<ac:macro ac:name="panel-hide">
<ac:parameter ac:name="page"><at:var at:name="parent," />home</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">top-level-page</ac:parameter>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="flag">registered-user</ac:parameter>
<ac:parameter ac:name="notflag">top-level-page</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">show-edit</ac:parameter>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
<ac:macro ac:name="panel-show">
<ac:parameter ac:name="page">Documentation</ac:parameter>
<ac:parameter ac:name="recurse">true</ac:parameter>
<ac:parameter ac:name="notflag">staff-user</ac:parameter>
<ac:rich-text-body>
<ac:macro ac:name="set-flag">
<ac:parameter ac:name="name">show-edit</ac:parameter>
<ac:parameter ac:name="state">false</ac:parameter>
</ac:macro>
</ac:rich-text-body>
</ac:macro>
Wiki Markup
{panel-hide:page=<at:var at:name="parent," />home}
{set-flag:top-level-page}
{panel-hide}
{panel-show:flag=registered-user|notflag=top-level-page}
{set-flag:show-edit}
{panel-show}
{panel-show:page=Documentation|recurse=true|notflag=staff-user}
{set-flag:show-edit|state=false}
{panel-show}
You can now toggle the edit links anywhere in your theme based on the show-edit
flag. This way, you don’t need to keep checking where you are in a space—top level pages, home page, documentation section—and the type of user you are—registered or staff.
Any developer looking at the flag logic above will see several optimizations that can be made; this is a key reason for separating the flag logic in to a wiki page so it’s easier to modify.
Where to Define Flags
We recommend using the flagLogic panel in the ThemeBuilder Skin Editor to store the flag logic for the following reasons:
Decluttering - reduce amount of markup in your theme panels
Maintainability - separate the flag logic from the theme customization
CSS Customization with Flags
When a flag is set, a class will be added to the HTML <body> tag. Let’s take thein-the-forum
flag we described earlier as an example:
<body class="flag-in-the-forum" ...
As you can see, the class is prefixed with flag-
, so remember that when you’re using it in your style sheet.
Let’s say you want to change the color of the first level heading when you’re in a forum; you could use this CSS in the CSS Tab:
.flag-in-the-forum h1 {
color: #0f0;
}
Flag Targets
Flags may be targeted against different types of scenarios; for instance, a user can set a flag against themselves. This is useful when implementing user preferences, such as whether to show a sidebar or not.
Target/Type | Level of Persistence | Permission Check |
Request | Not persisted, flag will be reset each time the page reloads | No permission check required since this flag can only affect the current user |
Session | Persisted against the user’s session, flag will be reset once the user closes and reopens their browser | No permission check required since this flag can only affect the current user |
User | Persisted against the user’s preferences, flag will remain but will only be available once the user is logged in | User must be logged in |
Page | Persisted against the current page, flag will be present when the current page is viewed by any user permitted to view the page | User must have write permission on the page/blog to set flag |
Space | Persisted against the current space, flag will be present when any page in the space is viewed | User must be a space or site admin to set the flag |
Global | Persisted for all spaces and global pages, flag will always be present | User must be a site admin to set the flag |
If a user does not have permission to set a flag, their request will be ignored.
Flag Target Priority
When a flag is read, no target type is supplied, which allows you to create default states for flags and enable customization by end users.
The following order is used when checking for a flag. If a flag is not defined, the next step will be checked, and if a flag is found either in the true or false state, it’s value will be used:
Request
Session
User
Page
Space
Global
Setting Flags Based on User Interaction
At times, it’s useful to provide links which allow users to set flags by clicking on something. This facility is provided through the Set Flag Link macro.