Applicability | This tutorial applies to Confluence 4.0, and later |
Level of experience: | This is an intermediate tutorial. You should have completed at least one beginner tutorial before working through this tutorial. See the list of developer tutorials. |
Time estimate: | It should take you approximately half an hour to complete this tutorial. |
This tutorial shows you how you can add a panel to the Insert Link dialog in Confluence. The plugin you will create inserts a new tab called Demo in the dialog. When you click the Demo tab, the Demo panel appears with a single text box:
Our plugin simply converts text entered in the field into an HTML link. This is a simple plugin, but provides a starting point for the more advanced link dialog customizations you might like to add to Confluence.
To create this plugin, you will create a Confluence plugin consisting of the following components:
When you have finished, all these components will be packaged in a single JAR file.
To get the most out of this tutorial, you should be familiar with:
We encourage you to work through this tutorial. If you want to skip ahead or check your work when you have finished, you can find the plugin source code on Atlassian Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:
1 2git clone https://bitbucket.org/atlassian_tutorial/confluence-insert-link-demo-plugin
Alternatively, you can download the source as a ZIP archive by choosing download here: https://bitbucket.org/atlassian_tutorial/confluence-insert-link-demo-plugin.
About these Instructions
You can use any supported combination of OS and IDE to create this plugin. These instructions were written using IntelliJ IDEA on Ubuntu Linux. If you are using another OS or IDE combination, you should use the equivalent operations for your specific environment.
This tutorial was last tested with Confluence 5.1.4.
In this step, you'll use an atlas
command to generate stub code for your plugin and set up the stub code as an Eclipse project. The atlas
commands are part of the Atlassian Plugin SDK. They automate much of the work of plugin development for you.
If you have not already set up the Atlassian Plugin SDK, do that now: Set up the Atlassian Plugin SDK and Build a Project.
Open a terminal and navigate to the directory where you want to place your project files.
Enter the following command:
1 2atlas-create-confluence-plugin
As prompted, enter the following information to identify your plugin:
group-id |
|
artifact-id |
|
version |
|
package |
|
Confirm your entries when prompted.
The SDK gave us most of the files we'll need for this plugin, and a few that we don't. For instance, it gave us several Java code stub files and test files for the code. This plugin doesn't use Java at all; it's entirely implemented with JavaScript and Soy. Some of these will interfere with our work, so let's deal with them first:
confluence-insert-link-demo-plugin
.src/test
.You can also remove the Java files from your project by removing the src/main/java
directory. However, removing those files is not necessary. Keeping them gives you a place to put Java code if you plan to expand this plugin in the future.
The SDK generated some resource files for us. However, we'll keep the resource files associated with this plugin in a separate directory, just for clarity.
First, create the Soy template used to generate our Insert Link panel:
src/main/resources/
insert-link
.
This is where we'll keep the resource files specific for our plugin.demo-panel.soy
.1 2{namespace Confluence.Templates.LinkBrowser} /** * The contents of the panel. */ {template .demoPanel} <div class="input-field"> <label for="demo-panel-destination">{getText('link.browser.demo.link.label')}:</label> <input type="text" tabindex="0" class="text" id="demo-panel-destination" name="destination" size="60"> </div> <div class="description">{getText('link.browser.demo.link.desc')}</div> {/template}
The namespace must be Confluence.Templates.LinkBrowser
, as shown here. The name of the template, demoPanel
, must be the key of your panel (as specified in the JavaScript file below) with the suffix -Panel
. In this case, our panel's key is demo
, so the template name is demoPanel
.
The template should contain the markup you want to appear in the body of the link dialog. In this case, we have a label with an i18n key of link.browser.demo.link.label
, a text box with the name destination
, and some description text with an i18n key of link.browser.demo.link.desc
.
Now add the JavaScript code:
In the src/main/resources/insert-link
directory, create a file named confluence-insert-link-demo-plugin.js
.
Add the following content to the file:
1 2/** * Initialisation and logic for the panel. */ (function($) { // Registers the tab when the Link Browser is created. AJS.bind("dialog-created.link-browser", function (e, linkBrowser) { var key = 'demo', // This panel's key $linkField, // The jQueryfied link input element. thisPanel, // A reference to this panel tab; // A reference to the tab tab = linkBrowser.tabs[key] = { // Called when the panel is created - register event handlers here createPanel: function (context) { thisPanel = context.baseElement; // panel initialisation logic here }, // Called when the panel is selected onSelect: function () { }, // Called when this panel is no longer selected onDeselect: function () { }, // Called when the submit button is clicked, before the location is retrieved preSubmit: function () { }, // Called before the dialog opens to determine which tab to highlight handlesLink: function (linkObj) { // return true if the link should be cause this panel to be selected return false; } }; }); })(jQuery);
This forms the scaffolding for our JavaScript code, with only placeholders for individual functions so far. We'll develop the logic for each function as we go. The important parts of this scaffolding are:
demo
must match the web-item link ID (see below) and the ID of the Soy template for the panel (see above).$linkField
variable will be used to keep a jQuery reference to our link field, which will be used in several of the handler functions.createPanel
, onSelect
, onDeselect
, preSubmit
and handlesLink
are hooks called by the Insert Link dialog as the tab is respectively: initialised, displayed, hidden, submitted and opened in edit mode.Replace the createPanel
function in the scaffolding with our initialization logic:
1 2// called when the panel is created - register event handlers here createPanel: function (context) { thisPanel = context.baseElement; $linkField = thisPanel.find("input[name='destination']"); // prevent enter submitting any forms when the button is disabled thisPanel.find("form").keydown(function(e) { if(e.keyCode == 13 && !linkBrowser.isSubmitButtonEnabled()) { e.preventDefault(); } }); // update the link to be inserted by the dialog when the user types $linkField.keyup(function (e) { AJS.log("link field keyup"); var url = $linkField.val(); var linkObj = url ? Confluence.Link.makeExternalLink(url) : null; if (linkObj) { // will enable the Submit button when a URL is added linkBrowser.setLink(linkObj); } }); },
This handler code does the following:
makeExternalLink
in the Confluence.Link
object. See link-object.js
in the Confluence source code for information about other link types which can be inserted.The only other handler we will implement for this tutorial is the onSelect
function, which will be as follows:
1 2// Called when the panel is selected onSelect: function () { // Defer focus to after dialog is shown, gets around AJS.Dialog tabindex issues setTimeout(function() { $linkField.focus(); }); },
This handler code focuses the link text box when the panel is opened.
Create a file named confluence-insert-link-demo-plugin.css
in the src/main/resources/insert-link/
directory.
Insert the following CSS code into the file:
1 2.demo-panel label { width: 54px; } .demo-panel .description { margin-left: 64px; }
Open src/main/resources/confluence-insert-link-demo-plugin.properties
for editing.
Add the following properties to the file:
1 2link.browser.tab.name.demo=Demo link.browser.demo.link.label=Link link.browser.demo.link.desc=The destination for the link
The CSS and properties files will provide the styling and text for our panel.
In the plugin XML descriptor file, src/main/resources/atlassian-plugin.xml
, we need to register a web item module to add the Demo tab to the dialog, as well as our i18n, JavaScript, Soy and CSS files.
Open the plugin descriptor file and replace the existing content with the following:
1 2<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2"> <plugin-info> <description>${project.description}</description> <version>${project.version}</version> <vendor name="${project.organization.name}" url="${project.organization.url}" /> <param name="plugin-icon">images/pluginIcon.png</param> <param name="plugin-logo">images/pluginLogo.png</param> </plugin-info> <!-- add our i18n resource --> <resource type="i18n" name="i18n" location="confluence-insert-link-demo-plugin"/> <web-item key="link-browser-tab" name="Link Browser Tab" section="system.editor.link.browser.tabs" weight="60"> <description>Displays a custom tab in the Link Browser.</description> <label key="link.browser.tab.name.demo"/> <link linkId="demo"/><!-- has to match the 'key' specified in the panel JS file --> </web-item> <web-resource key="insert-link-javascript" name="Insert Link Dialog JavaScript"> <!-- transform calls to AJS.getText() inside JS files --> <transformation extension="js"> <transformer key="jsI18n"/> </transformation> <!-- transform Soy templates into JS --> <transformation extension="soy"> <transformer key="soyTransformer"> <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions> </transformer> </transformation> <!-- JavaScript resources --> <resource name="demo.js" type="download" location="insert-link/demo.js"/> <resource name="demo-panel-soy.js" type="download" location="insert-link/demo-panel.soy"/> <!-- we need the editor resources to be loaded before these ones --> <dependency>com.atlassian.confluence.tinymceplugin:editor-javascript-resources</dependency> <!-- these resources will be included with any page containing the editor --> <context>editor</context> </web-resource> <web-resource key="insert-link-css" name="Insert Link Dialog CSS"> <!-- CSS resources --> <resource name="demo.css" type="download" location="insert-link/demo.css"/> <!-- we need the editor resources to be loaded before these ones --> <dependency>com.atlassian.confluence.tinymceplugin:editor-javascript-resources</dependency> <!-- these resources will be included with any page containing the editor --> <context>editor</context> </web-resource> </atlassian-plugin>
The important parts of the plugin descriptor are as follows:
linkId
attribute on the link (in this case "demo") must match the key of the plugin and the name of the Soy template, as noted above.context
of editor
, so they appear on any page containing the page editor. This means that your JS code will be included with the batch.js
file for pages that include "editor" in the URL.Because your JS code is loaded the editor context, it will be included with the "batch.js" file that includes "editor" in the URL.
That's it! Now let's try the plugin.
Now start up Confluence and try out your plugin:
Make sure you have saved all your code changes to this point.
Open a terminal window and navigate to the plugin root folder (where the pom.xml
file is).
Run the following command:
1 2atlas-run
This command builds your plugin code, starts a Confluence instance, and installs your plugin in it. This may take several seconds. When the process has finished, you will see many status lines on your screen concluding with something like the following:
1 2[INFO] confluence started successfully in 119s at http://atlas-laptop:1990/confluence [INFO] Type CTRL-D to shutdown gracefully [INFO] Type CTRL-C to exit
From your browser, open the Confluence URL indicated in the output.
At the Confluence login screen, enter the username/password combination of admin
and admin
.
Create a new page.
In the edit pane for your page, click the link icon.
Confirm that the Demo tab appears in the Insert Link dialog. Also, make sure that the link insert pane appears with no errors.
If the Demo tab does not appear in the dialog, make sure you have the web-item
correctly registered in atlassian-plugin.xml
. Also make sure that you have installed the plugin in Confluence and it is enabled.
If the panel itself is not working properly, check for JavaScript errors in the debugging console in your browser. Firebug or the WebKit inspector may help you debug your code and track down the problem.
Rate this page: