Skip to the content.

Back

Once you or your administrator has installed JavaScript Button for Confluence, add a new JavaScript button to a page by editing the page, starting to type /JavaScript and selecting the JavaScript Button extension:

insert button

Once the change to the page is published, you can invoke the action by clicking on the button:

invoke button

To edit the button, switch the page back to edit mode, hover over the button panel, end invoke the edit action:

edit button

Configuring the Button

In the edit panel, you can configure the following aspects of the button:

edit panel

Function Parameters

In the configuration section called Function Parameters, you can provide parameters that will be passed to your function when the button is invoked. For example, you can define a function to calculate the sum of two values like this:

Sum configuration

With the following JavaScript Code:

function sum(value1, value2) { 
  return `The sum of ${value1} and ${value2} is: ${Number(value1) + Number(value2)}`; 
}

The function named sum must have 2 parameters. When invoking the button, JavaScript Button for Confluence will pass 1 as value for the first parameter and 2 as value for the second parameter.

Note that the type of these parameters is string, hence if you want to calculate the sum of the two values you first have to convert them to a Number as shown above.

Field support

Now, so far this is not terribly useful. What we need is the ability to read information from a page to then analyze this information with a JavaScript function. That’s what a field is for.

A field is simply a line of text anywhere in the document consisting of a field name and a field value separated by a colon and a space like so:

Field

The Field in the example above has name Status and value Approved.

You can then define a Function Parameter such that JavaScript Button for Confluence will pass the value of a field to your function using the following syntax:

$('Status')

To get back to our sum example: You can add anywhere on your page, two fields for the two values, like so:

Value 1: 1
Value 2: 2

And then change the configuration for your sum function like this:

Field sum configuration

When the user invokes the Sum button now, Value 1 and Value 2 will be taken from the current page.

Store result to Field

Not only can you read field values to pass them as parameters to the function, you can also store the result of the function in a field. To do so use the same syntax as you use for Function Parameter for the Result Location, i.e.

$('Sum')

to store the result of the sum in a field named Sum.

Here is a complete example:

Field sum configuration with result

When invoking the button, the result is written into the Sum field:

Full-field example invoke

Remote Field Value

You can also read the value of a field on a page other than the one that contains the button. The syntax for Function Parameters is:

$('Field Name', $page(9175077))

Where Field Name is the name of the field on the page with id 9175077. You can find the id of the page in the URL shown in your browser:

Page Id in URL

This for example allows you to store configuration values for all your functions centrally on one page. You can even make this page read-only for most users.

Here is a full example of our Sum function that now shows the currency as configured in the Currency Field on page 9175077:

Remote Field

Resulting in (depending on the value of field ‘Currency’):

Sum: The sum of 10$ and 2$ is: 12$

Note that this is not supported when storing results to a field.

Fetch Code from a Field

With more complex scripts, it can become quite annoying to write the code in the small configuration panel. JavaScript Button for Confluence supports fetching code from a Code snipped Panel located on a page in confluence. To do so add a Code snipped panel to your page by typing /Code and hitting enter:

Code Panel Insert

Write the code into Code snipped Panel (you can even select JavaScript as the language for your code). Then give this Code snipped Panel a name, by writing its name directly above the panel, exactly as you do for fields:

Named Code Panel

You can then reference the code in the panel in the JavaScript Code section with the field syntax, like so:

Code Field Reference

Like any other field, the code field can also be remote using the page syntax like:

$('Sum of Two', $page(9175077))

Meaning, that you can host your JavaScript code on a central page and use it anywhere in confluence. You can even make this page read-only for normal users, so that normal user can not change/brake your code.

Console log

JavaScript Button for Confluence executes your JavaScript code on the server side and not on the client side. This means you can not debug your code with your browser’s debugger. However, to help you analyze your program, JavaScript Button for Confluence supports print debugging by providing you with a console to which you can log messages. These messages are shown to you in your browser’s console.

For example, when executing the following JavaScript code:

function sum(value1, value2) { 
  console.log("value1 is: " + value1);
  console.warn("About to calculate the sum");
  const result = Number(value1) + Number(value2); 
  console.info("The result is " + result);
  return result;
}

you will see the following statements printed to your browser’s console:

Console

The console supports the following functions:

Page support

Besides constant parameters and field parameters, JavaScript Button for Confluence also supports $page parameters. When using $page as parameter, the full page, including its content, will be passed to your function. For example:

Page Parameter

Will log the following to the console:

{ 
  id: '3801125',
  version: { 
    number: 3,
    message: '',
    minorEdit: false,
    authorId: '557058:6850f622-3434-4020-a9fd-9344832461fb',
    createdAt: '2023-06-02T19:41:01.879Z' 
  },
  authorId: '557058:6850f622-3434-4020-a9fd-9344832461fb',
  title: 'Example Page',
  status: 'current',
  body: { 
    atlas_doc_format: { 
      value: '{"type":"doc","content":[{"type":"paragraph","content":[{"text":"This is a paragraph.","type":"text"}]},{"type":"extension","attrs":{"layout":"default","extensionType":"com.atlassian.ecosystem","extensionKey":"cbd32dac-8a30-4df5-92ee-020f5ff40fcc/0fe673e4-25a3-485e-84d0-ba07480d3e3f/static/javascript-button","text":"JavaScript Button (Staging)","parameters":{"guestParams":{"resultLocation":"$dialog","code":"function print(page) {\\n console.log(page);\\n return JSON.stringify(page, null, \\"  \\");\\n}","functionName":"print","cqlQuery":"","caption":"Print Page","parameters":"$page"},"localId":"4495c6c3-f040-4e76-87c4-8e56e6d4b756","extensionId":"ari:cloud:ecosystem::extension/cbd32dac-8a30-4df5-92ee-020f5ff40fcc/0fe673e4-25a3-485e-84d0-ba07480d3e3f/static/javascript-button","extensionTitle":"JavaScript Button (Staging)"},"localId":"b90368e2-d64c-4154-b2b3-c2949066b0f6"}},{"type":"paragraph"},{"type":"paragraph"}],"version":1}',
      representation: 'atlas_doc_format' 
    } 
  },
  parentId: '33167',
  spaceId: '33085',
  createdAt: '2023-06-02T19:38:52.887Z',
  _links: { 
    editui: '/pages/resumedraft.action?draftId=3801125',
    webui: '/spaces/~5570586850f62234344020a9fd9344832461fb/pages/3801125/Example+Page',
    tinyui: '/x/JQA6' 
  } 
}

Learn more about the page format here: Pages Format

As for fields, you can also use $page as result location, this allows you to modify a page. For example, you can change the title of a page with following JavaScript Code:

function updateTitle(page) {
  page.title = "The new title";

  //You have to increase the version
  page.version.number = page.version.number + 1;

  //This is optional, but helps to keep track of changes
  page.version.message = "Updated title with JavaScript Button for Confluence";

  return page;
}

You can also use this approach to change the content of a page, for example, the following adds a new paragraph to the page when the button is invoked:

function addParagraph(page) {

  const pageBody = JSON.parse(page.body.atlas_doc_format.value);
  pageBody.content.push({
    type: "paragraph",
    content: [{
      text: "A new paragraph.",
      type: "text"
    }]
  });
  page.body.atlas_doc_format.value = JSON.stringify(pageBody);

  page.version.number = page.version.number + 1;
  page.version.message = "Added new paragraph";

  return page;
}

Learn more about the Atlas Document Format here: ADF

Last but not least: You can also create new pages. The following will create a new child page of the current page:

function createChildPage(page) { 
  return {
    parentId: page.id,
    spaceId: page.spaceId,
    title: "New Child Page",
    body: {
      representation: "atlas_doc_format",
      value: '{"type":"doc","content":[{"type":"paragraph","content":[{"text":"This is a paragraph.","type":"text"}]}],"version":1}',
    }
  }
}

Note that you can only read and write the current page and not a remote one using the $page(PAGE_ID) syntax. To modify other pages you can use CQL as explained in the next chapter.

CQL

By default, the JavaScript function is executed on the page on which the JavaScript button is located. But you can also provide a CQL Query (Confluence Query Language). The function is then executed on each page returned by the query. For example, you can execute the function on every page that contains the text (field) Type: Documentation and was created by the current user:

text ~ "\"Type: Documentation\"" AND creator = currentUser()

With this query and with the $page parameter you can for example create a button that will show the title of all Documentation pages created by the current user, like so:

CQL

CQL is very powerful, learn what you can do with it here: CQL

REST API Support

JavaScript Button for Confluence supports rest calls to Jira and Confluence Rest endpoints. You can for example fetch the content of any confluence page with the following script:

async function fetch(contentId) {
  const res = await api
    .asUser()
    .requestConfluence(route`/wiki/api/v2/pages/${contentId}?body-format=atlas_doc_format&serialize-ids-as-strings=true`);

  return await res.json();
}

Note that you have to mark your function as being async and you have to await the result of your rest call in order to make this work correctly. Learn more about the Confluence Cloud REST API here: The Confluence Cloud REST API

You can also make REST calls to the Jira API. For example, this script loads all Jira projects:

async function listJiraProjects() {
  const response = await api.asUser().requestJira(route`/rest/api/3/project`, {
    headers: {
      'Accept': 'application/json'
    }
  });
  console.log(`Response: ${response.status} ${response.statusText}`);

  const projects = await response.json();
  console.log(projects);
  
  return projects.map(project => `${project.key}: ${project.name} (id = ${project.id})`);
}

Learn more about the Jira Cloud Rest API here: The Jira Cloud platform REST API

This is very powerful, you can, for example, create a new Jira Task with the following code:

async function createIssue(projectKey, summary, description) {
  const projectId = await getProjectId(projectKey);
  const taskIssueTypeId = await getTaskTypeId(projectId);

  var bodyData = {
    fields: {
      description: {
        content: [
          {
            content: [
              {
                text: description,
                type: "text"
              }
            ],
            type: "paragraph"
          }
        ],
        type: "doc",
        version: 1
      },
      issuetype: {
        id: taskIssueTypeId
      },
      project: {
        id: projectId
      },
      summary: summary
    }
  };
  
  const response = await api.asUser().requestJira(route`/rest/api/3/issue`, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(bodyData)
  });
  
  console.log(`Response: ${response.status} ${response.statusText}`);
  const result = await response.json();

  return `New Issue created with key ${result.key}`;
}

async function getTaskTypeId(projectKey) {
  const response = await api.asUser().requestJira(route`/rest/api/3/issuetype/project?projectId=10000`, {
    headers: {
      'Accept': 'application/json'
    }
  });
  console.log(`Response: ${response.status} ${response.statusText}`);
  
  const issueTypes = await response.json();
  console.log(issueTypes);
  const taskId = issueTypes.find(element => element['name'] == 'Task')['id'];
  
  return taskId;
}

async function getProjectId(projectKey) {
  const response = await api.asUser().requestJira(route`/rest/api/3/project`, {
    headers: {
      'Accept': 'application/json'
    }
  });
  console.log(`Response: ${response.status} ${response.statusText}`);

  const projects = await response.json();
  console.log(projects);

  return projects.find(element => element['key'] == projectKey)['id'];
}

Note: With great power comes great responsibility.

Next

Check out our Examples

Back