Confluence links to create pages from templates

I’m working with Confluence to create a wiki for travel agents can record their research holidays. It is hoped that their colleagues can use first hand experiences of the resorts to promote them.

We wanted to have an easy and structured way for people to add pages, for which we’re using Confluence’s templates feature. Templates allow a two step page creation process:

  1. Enter information into a structured form (e.g. in our hotel page template, we ask for information on the food, accomodation and view), and select “insert variables” (I know, awful button title).
  2. Review what you’ve entered on the standard Confluence edit page (all the information from the form fields will have been inserted at the relevant points in the page).

A great piece of functionality but too many clicks involved. To create a templated page you have to:

  1. Click into the space administration section (already not ideal for a “regular” staff member)
  2. Select space templates from the menu
  3. Find the template you want
  4. Finally, select “create page from template”

With some technical jiggery-pokery I’ve managed to get this process down to one click, “create hotel page”, and I’ve done this without cracking into Java code (which is the programming language Confluence is written in).

The breakthrough discovery was that Confluence GET requests for this process. This meant I could create a link that would pass enough information so I could go straight to step 4 of the process above.

A quick diversion on POST vs GET: A form using GET sends it’s information by appending it to a URL (or web address); Google search is a good example of a GET form, have a look at the web address of a Google results page and you will see the words you searched for in the middle of a long string of other characters. A form using POST has a different method of sending the data, and does not append it to the URL. (Now back to my Confluence problem.)

The four pieces of information needed to make a page from a template are: the space key, the ID of new page’s parent, the title of the new page’s parent, the title of the new page and the ID of the template to use. To make a URL which would pass these pieces of information, I created a User Macro; User Macros are a way to define a site wide macro (i.e. Confluence wiki code). User Macros are created and edited from a page in the Confluence admin area.

Of the four pieces of information, the template ID was easiest to find: I looked at the web address in the link to edit the template, and there it was (e.g. pageTemplateId=1234).

Finding the ID of the parent was a bit more tricky, and I Googled around for quite a bit before discovering a way of getting it. There’s some Confluence data exposed in User Macros which you can use to add some limited additional information about the context of the User Macro (e.g. the page its in, the space that page is in, etc). One of the variables available is $content.id; when Confluence sees $content.id in a User Macro, it substitutes the ID of the current page when the User Macro is shown.

I could have hard coded the space key into the URL as it’s not going to change very often, but since I had discovered the use of variables in User Macros I wanted to be a bit smarter than that. Another variable available in User Macros is $space.key, which Confluence substitutes with the current space key (as you’d expect).

The user macro

My User Macro utilises the Adaptavist function compound-menuitem, which allows you to create a menu item and specify a custom URL for it. The completed User Macro looked as follows:

{compound-menuitem:custom|caption=make an activity page|link=/pages/createpage-entervariables.action?spaceKey=$space.key&parentPageString=@parent_title@&fromPageId=$content.id&title=@title@&linkCreation=false&templateId=360453|id=create_page}

You’ll need the following settings on the User Macro: untick “Macro has a body”, and set “Output” to “Macro generates Wiki markup”. You also need a unique value for the ID for every different User Macro.

You’ll notice that there’s two unspecified variables so far: the title of the parent page, and the title of the new page. I use a Javascript function to fill these in when the link is clicked.

The Javascript code

Once the link is on the page, we know (from the User Macro code above) the containing element will have an ID of “create_hotel”. From this we can write the following Javascript, using the excellent jQuery library (you’ll need to link in the jQuery library in order for this to work):

jQuery( document ).ready( docReady );
function docReady() {
initCreatePageButtons();
}
function initCreatePageButtons()
{
// Duplicate the next line and amend the text after the hash (#) to match your links
jQuery( '#create_page>ul>li>a' ).click( doCreatePage );
}
function doCreatePage()
{
var url = jQuery( this ).attr( 'href' );
// Fire a dialog to collect the new page title
var page_title_question = 'Please provide a title for your new page n(or press "cancel" to abandon creating the page)';
var page_title = requestPageName( page_title_question );
// If the user cancelled
if ( ! page_title ) {
// Return false, to prevent the link firing
return false;
}
// URL encode the page_title
var page_title_encoded = escape( page_title );
// Extract the page title from the H1 element. We could do this with Confluence in
// the user macro, using $content.title, but we can't URL encode from there so it's
// easier to do it here.
var parent_title_encoded = escape( jQuery( 'h1' ).text() );
// Replace the @parent_title@ token with the title gleaned from the dialog
var pt_re = /@parent_title@/gi;
url = url.replace(pt_re, parent_title_encoded);
// Replace the @title@ token with the title gleaned from the dialog
var t_re = /@title@/gi;
url = url.replace(t_re, page_title_encoded);
// Set the browser location to the new URL string
location.href = url;
return false;
}
function requestPageName( question )
{
var page_title = prompt( question, '' );
if ( page_title != null && page_title.length < 1 ) {
alert( "Sorry, but you must provide a page title for the new page." );
return requestPageName( question, '' );
}
// TODO: Validate title adheres to: page titles can not contain the following characters
// (:, @, /, , |, ^, #, ;, [, ], {, }, < , >) or start with ($, .., ~).
return page_title;
}

These functions do the following (not in order):

  • jQuery( document ).ready calls the function docReady when the document is ready to be used by Javascript.
  • docReady calls initCreatePageButtons.
  • initCreatePageButtons sets the onClick event on the relevant links so they call the second function, doCreatePage, when clicked.
  • requestPageName launches a prompt to the user for them to type in the title of the new page.
  • doCreatePage does most of the work: it fires the third function, requestPageName, to get the title for the new page, then looks up the title of the current page and does a “find and replace” operation on the URL to create this new page, then it changes the location of the browser to the completed URL and begins the process of creating our templated page.

Including the Javascript on the page

Now I needed to include the Javascripts on the relevant pages, I used another User Macro for this. Create a new User Macro and paste in the following code:

<script src="http://www.someserver.com/somedir/jquery.js" type="text/javascript" language="JavaScript">
<script src="http://www.someserver.com/somedir/jq_functions.js" type="text/javascript" language="JavaScript"></script>

You’ll need the following settings on the User Macro: untick “Macro has a body”, and set “Output” to “Macro generates HTML markup”. Then you want to add this User Macro as early in the page as you can; I put it in the Header area in my Theme Builder Layout.

So, in summary

I wanted a one click way of creating pages in Confluence using a structured form to make it easy for people to create page of particular types (in my case to describe hotels, resorts, etc for a travel wiki). To do this, I use a User Macro to create a URL which, when selected and visited, will start this process (skipping the first few steps normally required). Some custom jQuery Javascript then prompts the user for a page title, does the final preparation on the URL and, ta da, the user’s got to the template entry page in one click.

Join the Conversation

13 Comments

  1. hi, i’m also doing stuff in confluence, and i can see that you first piece of code goes in the user macro area, but where do you put all that javascript? are they in the same user macro? or a different one? or as html somewhere?

    thanks

  2. Hi John, Thanks for your leaving a comment. I use a separate User Macro to add in links to external Javascript files. The Javascript function initCreatePageButtons() would triggered from a document ready event, which runs (surprise!) when the document is ready. Hope that helps. I’ll do some more editing on the main blog post above to try and make it clearer.

  3. i’m really quite new to all this confluence stuff, so i’ve still got issues understanding this. Putting just your compoundmenu text into a user macro (with no wrapping) e.g. called quicktemplate, and then putting the “{quicktemplate}” into a page just echos the code above, and putting it into a menu structure doesnt appear, so do i need to wrap the code with some rendering code?
    The next thing I dont understand is how to link the javascript into the document ready event…

  4. Hi John. I’ll drop you an email with my IM details, and perhaps we can discuss this there? In the meantime:

    You’ll need the following settings on the User Macro: untick “Macro has a body”, and set “Output” to “Macro generates Wiki markup”.

    I’ve added some extra info in the blog post about using a User Macro to include the necessary Javascript. (It’s a bit long to paste into a comment.)

    Has that clarified anything?

  5. Great work!

    It seems that you might have missed an obvious item though. You can choose a template on the ‘Add Page’ screen, just above the markup editor. So four steps with certain permissions required becomes two steps with general permissions. Of course, you’d have to get them to make that second step :)

    Cheers!

  6. Hi Yancy, yes it can be quicker to do it that way, but as you say, it’s getting them to do that… in certain circumstances you want a nice obvious “add a blah page here” type links, to make it super simple for people.

  7. Another possibility, which gives you similar (but not exactly the same) functionality is to go to Confluence’s Administration page, Plugin Repository, enable Linking Plugin & Scaffolding Plugin (Linking Plugin seems to require Scaffolding). Then you can create a link in your Confluence page where when a user clicks on it they go immediately to page creation using a template you specify. For example:
    Click here to create a new {link-page:name=Some Title XXY |template=Your Custom Template|allowRename=true|parent=My Reports}page from some template{link-page}

    Explanation:
    link-page – is the macro from Linking plugin
    name – this will be put in the page title, which the user can edit during the page creation
    template – name of the template you want to use; space in name ok
    allowRename – user can rename title during page creation
    parent – parent page’s name for the newly created page. I think this must be pre-existing but am not sure. Spaces ok.
    The big disadvantage is that you have to first fill in template fields and click the “insert variables” before you get to the screen where you can edit the title and any other non-field parts and save the page.
    I hope that’s useful to somebody; was a bit confusing to figure out the syntax since it’s poorly documented.

  8. Another possibility, which gives you similar (but not exactly the same) functionality is to go to Confluence’s Administration page, Plugin Repository, enable Linking Plugin & Scaffolding Plugin (Linking Plugin seems to require Scaffolding). Then you can create a link in your Confluence page where when a user clicks on it they go immediately to page creation using a template you specify. For example:
    Click here to create a new {link-page:name=Some Title XXY |template=Your Custom Template|allowRename=true|parent=My Reports}page from some template{link-page}

    Explanation:
    link-page – is the macro from Linking plugin
    name – this will be put in the page title, which the user can edit during the page creation
    template – name of the template you want to use; space in name ok
    allowRename – user can rename title during page creation
    parent – parent page’s name for the newly created page. I think this must be pre-existing but am not sure. Spaces ok.
    The big disadvantage is that you have to first fill in template fields and click the “insert variables” before you get to the screen where you can edit the title and any other non-field parts and save the page.
    I hope that’s useful to somebody; was a bit confusing to figure out the syntax since it’s poorly documented.

  9. (note: I’m a confluence newb) I did a similar thing, however, I used a regular html form inside a user macro with a single button. This attaches the new page to the ‘space’ it’s currently in. (note the use of $content) I finished it up last night and haven’t had a chance to test it fully, but it seems to work for me. Also, I think the method ‘getRealTitle’ is depricated in newer versions of confluence… according to the docs, the new method is: ‘getDisplayTitle’

  10. Thanks a lot for this example, makes another favourite page in my browser !
    As Randy said, the scaffolding and linking plugin do have a quite same behaviour. However, the scaffolding plugin have some incompatibility problems with some plugins (I remember SQL plugin with SQLserver, making the Application server Freeze).

Leave a comment

Leave a Reply to Pope Poopinpants Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.