The Admin's tale - User Macro filtering a Confluence table

 admin.png

Once upon a time, there was a Confluence holding pages with very very large tables with lots of columns and even more rows. People used the browser's search function to jump to the data they need, but they asked for something that would hide all rows except the ones they were searching for. 

The Admin thought about it and this is what he found out:

What if one could add a search field on top of the table to filter out all unnecessary rows?

So, how can this be done? There is no built-in-feature like that and the admin didn't find a plugin for a reasonable prize, his budget was already spent for this year. So he decided to create a small custom user macro to implement this feature. 

User Macros can be implemented by Confluence administrators. The admin decides, whether the macro is just available for other admins or for all the other users when editing pages. 

The place where user macros are created is in the admin's section of Confluence. Here you find the menue item "User Macros".

Creating a new User Macro results in a form with these fields:

 usermacro5.png

Macro Name is the the name of the macro, of course... - but not the title of the macro (which is displayed in the macro browser).

Visibility - hide User Macros as long as they are not really really tested !

Macro Title - is displayed in the macro browser

Description - tell your users what your macro is doing - the description is displayed in the macro browser:

usermacro7.png

Next, the admin had to define, how the macro body should be processed. The processing options are described in detail on this page: https://confluence.atlassian.com/conf510/writing-user-macros-829077960.html

The admin tried a little bit and then decided that "No macro body" would be the right option, since the macro has just one parameter, but no body:

usermacro3.png

 So now take a look at the heart of the user macro, the template itself:

Each macro has a header consisting of these lines:

## Macro title: <your macro-title as stated above>
## Macro has a body: <Y or N>
## Developed by:
## Date created:
## Installed by:

I think, these parts are self-explanatory, but the next is not:

## @noparams

Parameter are the values, you enter when you click on a macro's edit button when you edit a page. So, yes, there are macros that don't have parameters. @noparams is the default.

But the admin thought, the user should decide, how wide the input field should be: short, medium, medium-long, long or full-width. These values were defined by Atlassian in their CSS and the admin used these, so that the new field has the look and feel of the other Atlassian page elements.

So he added the parameter as param0 to the template:

## @param 0:title=Length of the input field|type=enum|enumValues=short-field,medium-field,medium-long-field,long-field,full-width-field|default=long-field

And then, the user could set the length of the input field:

 usermacro4.png

Next, the admin had to define the input field. It is a regular HTML form with an input element. The class aui refers to the Atlassian User Interface CSS:

<form class="aui">
<input class="text $param0" type="text" id="searchInput" placeholder="Enter Search term"></form>

At last, the admin needed a script to filter out all the rows, where the search term is not included. He used JQuery, a "cross-platform JavaScript library designed to simplify the client-side scripting of HTML" (Wikipedia).

The Script is doing the following

  • if you type something into the field "searchInput", it hides every row of your table
  • then it looks at every row again: 
    • if it finds the term, the row is shown
    • if not, it stays hidden
  • table headers are always shown

And this is the script:

<script type="text/javascript">
AJS.$("#searchInput").keyup(function () {
var jqry = AJS.$
var rows = jqry("tr").hide();
if (this.value.length) {
        var data = this.value.split(" ");
        jqry.each(data, function (i, v) {
                rows.filter(":contains('" + v + "')").show();
        });
} else rows.show();
AJS.$('thead tr').show();
});
</script>

And this is how it looks on the Confluence page:

The unfiltered table:

 usermacro-unfiltered.png

 

The same table filtered with the term "12":

 usermacro-filtered.png

What's left?

This is just a very simple basic filter. Soon, the admin's people asked for more:

  • search in a specific column
  • filter with wildcard characters
  • filter a specific table (in this example, each table on the page is filtered with the one and only input field)

But the admin had a lot more things do do and so, this filter remained the same until now ...and they all lived happily ever after.

Maybe another admin will add some new features to the basic filter... Sometimes

7 comments

Davin Studer Community Champion Apr 05, 2017 • edited on Apr 05, 2017

This is how I would do bullet point three ....

Set the macro body processing to Rendered. Put your table inside the macro body. Then in your template do something like this ...

## provides a unique number that can be used to target this user macro only
#set( $id = $action.dateFormatter.calendar.timeInMillis )

<div id="tableFilter$id">
$body
</div>

Now you can target each table individually in jQuery like this ...

AJS.$('#tableFilter$id tr')
Thomas Community Champion Apr 06, 2017

Hi Davin,

thank you for your suggestion! I will try that as soon as possible.

Fabian Lopez Apr 11, 2017

Very good article. Thanks for sharing!

Daniel Eads Community Champion Apr 12, 2017

Nice! The Table Filter and Charts plugin can provide this functionality as well as more gravy, but this is a great example of doing something with a user macro. There's a lot of possibilities without having to develop an entire plugin!

Arni Yabut Apr 20, 2017

I love this, thanks for sharing! :)

 

Nice!  This is helpful!

Thomas Community Champion Monday

@Fabian, Daniel, Arni and David - thank you. I'm glad you like the article :-)

Comment

Log in or Register to comment