This documentation relates to an earlier version of Atlassian Gadgets.
View

Unknown macro: {spacejump}

or visit the current documentation home.

This page tells you how to create a gadget using the Atlassian Gadgets JavaScript Framework.

JavaScript Framework is currently in JIRA only

The Atlassian Gadgets JavaScript Framework is currently part of the JIRA project. It will eventually be moved into Atlassian Gadgets. See AG-622. Until that merge is completed, you will only be able to use the framework if you are developing gadgets for JIRA.

On this page:

High-Level Format for Creating a Gadget

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:

var gadget = AJS.Gadget({
    baseUrl: "__ATLASSIAN_BASE_URL__",
    useOauth: ..., 
    config: ...,
    view:...
});

ここで:

  • baseUrl — A required option used to pass the base URL to the framework. The framework uses this URL for prefixing relative Ajax requests and also makes it available from gadget.getBaseUrl() and AJS.gadget.getBaseUrl().
  • useOauth — An optional parameter, with a URL value, that determines the type of authentication used. There is more detail in the authentication section below.
  • config — You can use this optional parameter to define the configuration form. If this parameter is not defined, it is assumed that the gadget has no configuration options. Please note that this is not the built-in Opensocial Gadget configuration screen. The latter did not meet our needs so we decided to implement our own. See below.
  • view — This object defines the view to display. See below.

認証

The framework will automatically try to broker an authenticated connection to the server, based on the URL provided in the useOauth configuration option.

useOauth: URL — Here you must provide a URL that requires authentication. Typically we use a URL value of "/rest/gadget/1.0/currentUser".

The framework will then try to broker an authenticated connection in the following order:

  1. Current session (a gadget being served locally, e.g. JIRA displaying a JIRA gadget), then
  2. A Trusted Applications connection, then
  3. OAuth. A gadget being served in a non-Atlassian container will typically use OAuth.

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:

  1. Local — We can determine whether the gadget is being served locally (e.g. JIRA serving out a JIRA gadget) and then we can just sue the local browser to talking to the server. This is the most efficient method of communication as no proxies are used.
  2. Trusted Applications — If a successful request returns from the supplied resource when no OAuth token is passed, it must be a trusted application. We rely on the container server to use its Trusted Applications connection to the remote server for authentication.
  3. OAuth - If the previous two methods fail, we fall back to OAuth.

More: Using Authentication in your Gadget

Configuration Form

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:

        <Require feature="setprefs" />
        <Require feature="views" />
        <Require feature="dynamic-height" />

ここで:

  • setprefs — This is required to persist user preferences.
  • views — This is used to determine whether the current user can edit the preferences or not. Please note that this is an Atlassian-specific extension to the feature and will not work in other containers. The edit button will always be shown in other containers.
  • dynamic-height — Provides dynamic height adjustment in the config screen, view creation and on resize.

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.

(info) All fields on the configuration form will be persisted as UserPrefs against the gadget.

...
config: {
    descriptor: function(){...}, 
    args: {Function, Array}
},
...

ここで:

  • descriptor — This function returns a new Configuration Descriptor
  • args — Either an array of objects or a function that returns one. The objects in this array have two keys:
    • (String) key — Name of key that will be used to access the data from within the template.
    • (Object) ajaxOptions — Set of request options to retrieve data from remote resource. Options are available here. If a String is used, it will just retrieve the REST resource assuming it is JSON.

Ajax Options

This can either be an array of options to retrieve, or a function that returns a similar array.

...
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
]
...

ここで:

  • key — The descriptor will be able to access the results of the Ajax call via this key, e.g. args.key.
  • ajaxOptions — If this is a string, the framework assumes it is the URL to a REST resource returning JSON. However, this can be a more complex jQuery-style remote call definition. Options are available here.

jQuery style remote Ajax options

...
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 endpoint. The example will not work.

Configuration Descriptor

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.

...
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
        ]
    };   
},
...

ここで:

  • args — This is an object populated by the results of the Ajax options defined in the args parameter of the config object. If you retrieve a list of projects via Ajax, this list can be accessed via: args.projects
  • action — This is a URL pointing to a REST resource that will validate the form and return appropriate errors if the form contains invalid data. Please see expected REST endpoint formats for the structure and return codes of the response.
  • theme — This tells the form how to lay itself out. There are two possible values:
    • "top-label" — This displays the field label above the field. Useful for narrow forms.
    • "long-label" — This displays the label on the same line as the field. Better suited to forms with a lot of width available.
  • fields — This is an array of field objects.

More: Theming your Gadget Dynamically

Configuration Fields

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.

    <UserPref name="project" datatype="hidden" />

We support the following types of fields (details are on the Field Definitions page):

  • Hidden fields — A hidden input area on the form whose value is passed back to the server during validation and preference saving.
  • Text input — A single line text input.
  • Text area — A text area for accepting larger text inputs.
  • Select fields — A simple selection list that displays a list of options. It is possible to display a list of options retrieved from a REST resource.
  • Multi-select fields — A multi-select field where it is possible to select multiple values. It is possible to display a list of options retrieved from a REST resource.
  • Radio button group — A set of radio buttons for selecting unique values. It is possible to display a list of options retrieved from a REST resource.
  • Check box group — A set of check boxes to select multiple values. It is possible to display a list of options retrieved from a REST resource.
  • Custom fields — A user defined field. This allows users to insert arbitrary HTML into the form.
  • Callback builder — An empty <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 above.

config: {...},
view: {
    enableReload: true,
    onResizeReload: true,
    onResizeAdjustHeight: false,
    template: function (args) {},
    args: [{
        key: "chart",
        ajaxOptions: {...}
    }]
}    

ここで:

  • enableReload — (Optional.) Adds a reload icon to the bottom of the gadget and adds a reload period option to the configuration form. The gadget will redraw the view every X minutes.
  • onResizeReload — (Optional.) When the browser window resizes or the layout changes, the gadget redraws the view. This is used in our chart gadgets so that the chart image can be regenerated to size and granularity.
  • onResizeAdjustHeight — (Optional.) When the browser window resizes or the layout changes, 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.
  • template — A function that is responsible for creating the view. See below.
  • args — Either an array of objects or function that returns one. The results of these remote calls are passed in to the template during rendering.
    • key — Name of the key that will be used to access the data from within the template.
    • ajaxOptions — Set of request options to retrieve data from a remote resource. Options are jQuery Ajax options.

View Template Function

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.

例:

view: {
    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")
                }
            };
        }
    }]
}
関連トピック

Using the Atlassian Gadgets JavaScript Framework
Writing an Atlassian Gadget
Gadgets and Dashboards Development Hub

  • ラベルなし