Introduction to the Javascript API
Contents
Overview
The purpose of the v3 Javascript API is to provide powerful functionality for interacting with your Jive instance from within a Jive App. The v3 API provides far more features than the previous v2 API. Almost any action that can be performed through the user interface can be done programmatically using the v3 API. The API also exposes some functionality of the Admin Console. Extensive metadata about the available Classes and Static Methods can be obtained with the metadata
static class.
All requests and responses use JSON data with attached javascript methods. The JSON format for different Jive objects is given in the Classes section (see sidebar). Fields marked as required must be specified when creating and updating objects. Optional fields can be specified on create and update, but the request will succeed whether or not they are provided. Fields marked as read-only are returned as data in responses. Read-only fields will be ignored for create requests. When updating an entity, fields marked as required and optional can be modified, but read-only fields should not be modified. As an example, the Document
page describes the full JSON format for a document. The documents
static method page gives the minimum JSON for creating a new document.
The most important types and methods in the API fall into four categories:
- Content
- Places
- People
- Activity
Content includes the Classes Document
, Discussion
, Poll
, and Post
(see "Classes" in the sidebar.) Static classes to manipulate content include contents
, discussions
, polls
, etc. These must be prefixed with namespace osapi.jive.corev3
. The contents
static class is special in that it can perform any static functionality provided by the more specific static classes (e.g. discussions
). The type
field must be provided when using the contents
static class.
Place Classes include Blog
, Group
, Project
, and Space
. Static classes for manipulating places include blogs
, places
, groups
, and projects
. The places
static class can perform any functionality provided by the other static place classes.
People, or Jive users, are manipulated with the Person
Class and the people
Static Class. The Member
Class and members
Static Class are used for adding users to groups.
Classes related to Activity include Action
, Activity
, InboxEntry
, and StreamEntry
. Similar to Content, Places, and People, there are corresponding static classes.
App Setup
The only requirement is to add the following line to yourapp.xml
file inside ModulePrefs
.<ModulePrefs
> ... <Require
feature="jive-core-v3" /> ... </ModulePrefs
>
Organization
The v3 Javascript API is organized into three main sections:
- Static Classes
- Classes
- Extendable
Static Classes
The artifacts that are listed under "Static Classes" are collections of static functions that are used as entry points into the API. These methods are generally used to obtain instances of the non-static classes; however, there are some operations that can be done directly with the static functions.
For example, to get a person, the following code can be used:
// get the request that will fetch a person by username var request = osapi.jive.corev3.people.get({username: 'admin'}); // execute the request request.execute(function(response) { if (response.error) { var code = response.error.code; var message = response.error.message; // present the user with an appropriate error message } else { var person = response; // use the person object as appropriate } });
Classes
The artifacts that are listed under "Classes" provide an object oriented view of the Jive system. Instances of these classes are never constructed directly. They are obtained through calls to one of the static class methods. Once an instance is obtained, the properties and methods of that class can be accessed in the standard Javascript fashion.
For example, if a person is obtained as described above, that person's blog can be obtained directly from the person object:
// ensure that blog is accessible if (person.getBlog) // get the request that will fetch the user's blog var request = person.getBlog(); // execute the request request.execute(function(response) { if(response.error) { var code = response.error.code var message = response.error.message // present the user with an appropriate error message } else { var blog = response; // use the blog object as appropriate } }); }
Extendable
The artifacts that are listed under "extendable" are not first class elements in the Core API. That is, they can not be instantiated or manipulated directly. Instead they are used to add compound fields to the non-static classes. For example, the ContentBody item is used to encapsulate the content body of a Jive content object, which in turn has type
and text
fields.
Authentication
In order to use the Core API, the user running the app needs to be authenticated with the Jive container. The way that this happens is outside of the scope of this API. It is generally done by logging into Jive via the web UI. Once this is done, the app and all of its Core API calls run with the permissions of that logged in user.
If the current user does not have permission to perform an action, then the corresponding method will be undefined. For example, if the current user does not have permission to delete a person, then the destroy
function will be undefined on that person entity.
Important Features
Jive Request Objects
How they work
Throughout the Javascript API, it is implied that any function (static or non-static) returns a Jive request object. Making requests with Jive request objects is similar to usingjQuery.ajax()
or XMLHttpRequest
objects. However, the process is simplified somewhat and there are important differences. The requests are always asynchronous, and a callback function taking a single argument must be specified. Since the request is performed inside an app container, the returned objects have functions specific to Jive rather than being purely data objects. There are no separate success and error callbacks---the user must check if an error occurred. If an error occurred, the error
field will exist. Otherwise, a Jive entity is returned, typically the object created, updated, or fetched. The only exception is that requests to destroy an object return a simple JSON with a status
field that should have the value ‘204’ (no content) if the request succeeded. Following is an example response if an invalid date is given with a create request (see date format):{ "error":{ "code":400, "message":"Invalid date format 2012-07-05" }, "status":400 }The typical workflow:
- Setup the JSON required to perform the request, e.g. see announcement creation for the minimal JSON required to create an announcement. See documentation on individual entities for fields that can be used on create and update.
- In the case of updating an entity, use the existing entity. Modify the fields to be updated before obtaining the request object with
var request = someEntity.update()
. - Obtain a request object
- Call
execute()
on the request object, passing in the required callback
Batch requests
To improve performance when performing multiple requests, batch requests are possible. This is done by obtaining a new batch object, and then adding key-value pairs where the values are Jive request objects. For example, the following code would create 3 announcements:function createAnnouncements() { var announcement1 = { subject : "A test announcement 1", content : {text:"<p>Test Announcement 1</p>"} }; var announcement2 = { subject : "A test announcement 2", content : {text:"<p>Test Announcement 2</p>"} }; var announcement3 = { subject : "A test announcement 3", content : {text:"<p>Test Announcement 3</p>"} }; var batch = osapi.newBatch(); batch.add("announcement1", osapi.jive.corev3.announcements.create(announcement1)); batch.add("announcement2", osapi.jive.corev3.announcements.create(announcement2)); batch.add("announcement3", osapi.jive.corev3.announcements.create(announcement3)); batch.execute(function(data) { if (data.error) { //handle error } console.log("First announcement's subject: " + data["announcement1"].subject); console.log("Second announcement's subject: " + data["announcement2"].subject); console.log("Third announcement's subject: " + data["announcement3"].subject); }); }
Paginated Lists
Throughout the API, methods that return arrays of objects return special Jive Paginated Lists. These objects always contain the following fields:
Properties | Type | Description |
---|---|---|
list | JSON Array | Array containing the retrieved Jive objects |
startIndex | integer | The current page's offset into the list of all results |
itemsPerPage | integer | The max number of items returned per page. Usually set with the count query parameter. |
links | JSON Object | Object containing URLs for getting the next or previous page of results. Has fields next and prev (when available). |
osapi.jive.corev3.people.get
returns a list object represented by the type Person[]
, not to be confused with a Javascript array type. List objects have a getNextPage
function that returns a request to get the next page of objects. Note that this function is undefined when there are no more results to retrieve, so you must check if it exists when retrieving multiple pages. For example, to get a list of places with 1 item per page, one could execute the following code:// get the request to retrieve a list of places, 1 per page var request = osapi.jive.corev3.places.get({count: 1}); // execute the request request.execute(function(response) { if (response.error) { var code = response.error.code; var message = response.error.message; // present the user with an appropriate error message } else { var place1 = response.list[0]; // process the first place returned } });
Example JSON of a returned list object containing a single blog (resources omitted for brevity):
{ "startIndex":0, "links":{ "next":"places?sort=titleAsc&fields=%40all&count=1&startIndex=1" }, "itemsPerPage":1, "list":[ { "type":"blog", "status":"Active", "parent":"/people/2355", "contentTypes":[ "post" ], "id":"1195", "visibleToExternalContributors":false, "updated":"2012-08-10T15:52:59.707+0000", "description":"Description of some blog created on Fri Aug 10 2012 08:52:59 GMT-0700 (PDT)", "name":"Blog created at Fri Aug 10 2012 08:52:59 GMT-0700 (PDT)678245", "displayName":"Some_blog_872404", "published":"2012-08-10T15:52:59.707+0000", "followerCount":1, "viewCount":0 } ] }
As an advanced example, here is sample code to recursively process elements of a list by page:
//Argument: a request object that returns a Jive list function processListByPage(request) { //Execute the request to get a list request.execute(function(response) { if (response.error) { var code = response.error.code; var message = response.error.message; // present the user with an appropriate error message } else if (!response.list) { alert("Error: response is not a list!"); } else { for (var i = 0; i < response.list.length; i++) { //Process each element in this page } if (response.getNextPage) { var requestNextPage = response.getNextPage(); processListByPage(requestNextPage); } } }); }
Date Format
The Date format used is based on the ISO 8601 standard, but has additional restrictions. The time field and the timezone must be included. For example, September 1st 2012, 11 AM in GMT would be written as2012-09-01T11:00:00.000+0000
. Note that the UTC offset is required, because Jive uses UTC time to avoid ambiguity. In this case the offset is +0000 for GMT. The milliseconds are also required. Since Jive 6.0.3 and above, Jive provides static methods for parsing and formatting dates. The methods are osapi.jive.corev3.parseDate(dateString)
and osapi.jive.corev3.formatDate(aDate)
.osapi.jive.corev3.parseDate
is specifically for parsing dates returned from Jive in JSON objects, but it will fall back to using the standard Javascript date parsing, so you can use it throughout your code. It returns null on failure. For versions prior to Jive 6.0.3, most browsers can parse ISO 8601 dates, so using the Date class's constructor should work on the dates returned from Jive inside JSON objects. If this fails, you can use sample code at the bottom of this section. Here is an example of retrieving a document and parsing the publish date.var request = osapi.jive.corev3.documents.get(); request.execute(function(docs) { var firstDoc = docs.list[0]; var datePublished = osapi.jive.corev3.parseDate(firstDoc.published); console.log("Parsed a document's publish date from Jive: " + datePublished); });
osapi.jive.corev3.formatDate
is for converting a Javascript Date object into a string suitable for sending to Jive. There are several cases where you can provide a date, such as when choosing the endDate
for an announcement. Here is an example of creating an announcement, providing the current date + 10 days as the endDate
var endDate = new Date(); endDate.setUTCDate(endDate.getUTCDate() + 10); var dateString = osapi.jive.corev3.formatDate(endDate); var announcement = { subject : "A test announcement to expire in 10 days", content : {text:"<p>Test Announcement</p>"}, endDate: dateString }; var request = osapi.jive.corev3.announcements.create(announcement); request.execute(function(created) { console.log("Created this announcement", created); });To format a
Date
object when osapi.jive.corev3.formatDate
is not available (before Jive 6.0.3), the following function can be used:function formatJiveDate(date) { if (Date.prototype.toISOString) { return date.toISOString().replace(/Z$/, "+0000"); } function pad(number) { var r = String(number); if ( r.length === 1 ) { r = '0' + r; } return r; } return date.getUTCFullYear() + '-' + pad( date.getUTCMonth() + 1 ) + '-' + pad( date.getUTCDate() ) + 'T' + pad( date.getUTCHours() ) + ':' + pad( date.getUTCMinutes() ) + ':' + pad( date.getUTCSeconds() ) + '.' + String( (date.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ) + '+0000'; }To parse a date string when
osapi.jive.corev3.parseDate
is not available (before Jive 6.0.3), the following function can be used:var dateRegex=/(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)\.(\d\d\d)\+0000/; function parseJiveDate(dateString) { //First try to match the strict date format from Jive var match = dateRegex.exec(dateString); if (!match) { //On fail, fall back to default date parsing return new Date(dateString); } var year = parseInt(match[1]); var month = parseInt(match[2]) - 1; //javascript expects a month between 0 and 11 var day = parseInt(match[3]); var hour = parseInt(match[4]); var min = parseInt(match[5]); var s = parseInt(match[6]); var ms = parseInt(match[7]); var d = new Date(); d.setUTCFullYear(year, month, day); d.setUTCHours(hour, min, s, ms); return d; }To parse ISO 8601 dates in Java, see the REST API documentation.
Filters and Searching
Throughout the API, requests to get paginated lists of objects provide filters and search functionality for improving the results. For example, the static method contents.get allows for the filters author, count, fields, place, search, startIndex, tag, and type. The count and startIndex fields are described above for paginated lists. Providing the search field performs a search based on text in the content of objects, typically searching thesubject
, description
, and content
or content.text
fields (for types containing these fields). The search field supports wild cards. For example, if you want to search for "Bob Smith Jones" but you don't know that his middle name is "Smith", then you can search for "Bob*Jones".Versioning
Some classes and methods have a Since label that identifies which iteration of the Core API this feature was added in. Items with no Since label have been available in Jive Cloud since the Summer 2012 refresh. Other values have the following meaning:
Since: 3.0
- Available in Jive 6.0, and late 2012 in Jive Cloud.