This page tells you how to create a gadget using the Atlassian Gadgets JavaScript Framework.
The framework uses a declarative approach in terms of configuration. View, configuration and authorisation parameters are passed into the constructor and used to configure the gadget. See Gadget Object API for methods available on the gadget object.
The top-level options are:
1 2var gadget = AJS.Gadget({ baseUrl: "__ATLASSIAN_BASE_URL__", useOauth: ..., config: ..., view:... });
Where:
gadget.getBaseUrl()
and AJS.gadget.getBaseUrl()
."/rest/gadget/1.0/currentUser"
. The framework will then try to broker an authenticated connection in the following order:
The framework will automatically try to broker an authenticated connection to the server, based on the URL provided in the useOauth
configuration option described GADGETDEV:above. If the value passed in is "always"
, the framework will always try and use OAuth. If the value passed in is a URL, the framework will determine the best method of invoking that URL. The URL must not allow anonymous access. JIRA currently provides the following REST resource:
/rest/gadget/1.0/currentUser
The framework tries to connect to the server in the following order:
More: Using Authentication in your Gadget
Early on in our Gadget development, we realised that the OpenSocial gadgets' mechanism for creating configuration forms was not going to meet our needs. The fields must all be known beforehand, options are static and fields cannot be manipulated programatically. OpenSocial also only supports very basic fields. Our framework offers all the options available in the Opensocial Gadget framework for creating a configuration form. In addition, our framework allows for Ajax populated lists, custom fields and even dynamically included fields.
Typically, when loaded, a gadget will show a config screen first, then the normal gadget view. The user can choose to view it in canvas view if defined.
In order to take full advantage of the features in the framework, you should include the following in your gadget XML:
1 2<Require feature="setprefs" /> <Require feature="views" /> <Require feature="dynamic-height" />
Where:
The config
object consists of two parts: Ajax option definitions and a descriptor. When the form is generated, the Ajax options are retrieved and then fed into the descriptor which then returns an object fully defining the configuration form. The framework will then render the form.
When the form is submitted, the form will use the passed in validation URL to validate the form and if successful, will then save the preferences to the server. If validation fails, the form will display the errors inline.
All fields on the configuration form will be persisted as UserPrefs against the gadget.
Where:
This can either be an array of options to retrieve, or a function that returns a similar array.
1 2... args: [ { key: "key to access options by", ajaxOptions: "/rest/gadget/1.0/projects" /* this can also be a more complex JQuery style remote call */ }, ... more options to retrieve ] ...
Where:
args.key
.jQuery style remote Ajax options
1 2... args: [ { key: "project", ajaxOptions: { url: "/rest/gadget/1.0/projects", data: { restrictToPermission: "create" }, type: "POST" } }, ... more options to retrieve ] ...
Note: This is just a fictitious REST resource. The example will not work.
The configuration descriptor is a function that returns an object defining the configuration form. After the Ajax options have been retrieved, they are passed into the function to get the object that defines the form.
The function is called within the scope of the gadget. Hence this
refers to the current gadget object.
1 2... descriptor: function(args){ /* This is called within the scope of the current gadget. "this" refers to the current gadget */ return { action: "validation url", /* A url to validate the form against */ theme: "", /* The layout of the form - "top-label" or "long-label" */ fields:[ { /* Field descriptor */ }, ... more fields ] }; }, ...
Where:
args
parameter of the config
object. If you retrieve a list of projects via Ajax, this list can be accessed via: args.projects
More: Theming your Gadget Dynamically
Configuration forms are made up of list of fields. Typically, these fields relate to UserPref fields defined in the gadget XML. We usually define our UserPrefs in the XML as hidden UserPrefs. This will ensure that the field will not appear in the OpenSocial gadget configuration form. E.g.
1 2<UserPref name="project" datatype="hidden" />
We support the following types of fields (details are on the Field Definitions page):
<div/>
is inserted into the form. After form creation, a callback handler is called passing in the jQuery wrapped div
. This is the most powerful field creation technique and can be used to build highly interactive fields.More:
This object defines the view to display, as shown in the high level overview GADGETDEV:above.
1 2config: {...}, view: { enableReload: true, onResizeReload: true, onResizeAdjustHeight: false, template: function (args) {}, args: [{ key: "chart", ajaxOptions: {...} }] }
Where:
gadget.adjustHeight()
is called to ensure that if any lines changed their wrapping the gadget height will adjust accordingly. You must include the dynamic-height
feature for this to work.The template
function is responsible for rendering the gadget's view. The function is run within the scope of the gadget so 'this
' refers to the gadget. See the Gadget Object API for the methods available.
The template creates HTML using jQuery. It does not include styling. Styling is done later via CSS.
The function takes one argument - args
- a map containing the response from the Ajax calls. This map is keyed by the specified key.
The function must be able to be called multiple times for reloading and resizing.
Example:
1 2view: { enableReload: true, onResizeAdjustHeight: true, template: function (args) { var gadget = this; var filters = args.favFilters.filters; if (!filters){ gadget.getView().removeClass("loading").html("<p>__MSG_gadget.favourite.filters.no.favourites__</p>"); } else { var list = AJS.$("<ul/>").attr("id", "filter-list"); AJS.$(filters).each(function(){ list.append( AJS.$("<li/>").append( AJS.$("<div/>").addClass("filter-name").append( AJS.$("<a/>").attr({ target: "_parent", title: gadgets.util.escapeString(this.description), href: "__ATLASSIAN_BASE_URL__/secure/IssueNavigator.jspa?mode=hide&requestId=" + this.value }).text(this.label) ) ).append( AJS.$("<div/>").addClass("filter-count").text(this.count) ).click(function () { if (window.parent){ window.parent.location = "__ATLASSIAN_BASE_URL__/secure/IssueNavigator.jspa?mode=hide&requestId=" + this.value; } else { window.location = "__ATLASSIAN_BASE_URL__/secure/IssueNavigator.jspa?mode=hide&requestId=" + this.value; } }) ); }); gadget.getView().html(list); } }, args: [{ key: "favFilters", ajaxOptions: function () { return { url: "/rest/gadget/1.0/favfilters", data: { showCounts : this.getPref("showCounts") } }; } }] }
Rate this page: