Widgets: Frequently asked questions

Here you can find answers to questions on developing and manipulating widgets.

What is a widget?

Widgets provide a way for administrators to customize the space, project, social group and system widgetized pages (Overview tab and the community Home page). They're a simple to create combination of Java code and FreeMarker templates that can be deployed as a plugin.

Is there a way to tell if the view that I'm rendering is in edit mode or in view mode?

The WidgetContext, which should be available in your FreeMarker template as widgetContext, has an isEdit() method. This method should give you the ability to show a different view if the widget is being rendered as part of a editing session.

Is it possible to add widgets to non-overview tab pages?

Not at this time, no.

Is it possible to display widgets outside the application?

Not at this time, no. However, there are a number of ways that you can expose content to other systems, by using either RSS or JSON.

Can you put multiple widgets of the same type on a page?

Yes, although if you do this and your widget uses JavaScript to refer to various parts of the template, you should append an identifier to the DOM element ID's that you create or manipulate. An example of how to do that is in the /template/widget/your-statusupdates.ftl template, which contains this line of code at the top of the template:

<#assign idPrefix = StringUtils.randomString(6) />

Then later in the page a <div> element in the widget can be referred to like this:

<div id="current-status-${idPrefix}">

Is it possible to get a reference to the current user in the Widget class or widget template?

Yes, the current user is part of the WidgetContext interface that gets passed to your plugin's render method. If your widget extends BaseWidget, then you can call applyFreemarkerTemplate() which calls loadProperties() and adds the WidgetContext to the FreemarkerContext, and from there you can access the current user. 

Also, if you override loadProperties() then you can add whatever other run-time props you want to access in your FTL file.

What files do I have to create in order to add a widget via a plugin?

You need a plugin.xml with a <widget> element pointing to a class that implements the Widget interface (or that extends BaseWidget).  That's the bare minimum and assumes no design-time properties. If you want design-time props, then you need a properties file in the beans folder, and a @PropertyNames annotation at the class level that defines the design-time properties.

How does the popularity algorithm in the popularity widget work?

PopularityDeterminationTask is the class that handles the majority of the work. It runs every 15 minutes (as configured in spring-taskContext.xml, which means you can probably change it via a plugin in 2.1 if you want) and works closely with ActivityManagerImpl. Every time it runs it does the following things:

  • Iterates over the set of containers in the community (spaces, projects, social groups and blogs).
  • Calculates the popularity of each item in the in-memory copy of activities that activity manager maintains for the current day. The score (or popularity) of each item is calculated by adding together the score of each activity on an item, the scoring is as follows:
    • each view is given 1 point
    • each modification (documents only) is given 5 points
    • each comment (blogs and documents) or reply (thread) is given 5 points
  • Calculates the popularity of items in each container stored in the database (a popularity score is computed for each item based on the activity that happened that day every night at midnight; this data is stored in the jivePopularity table) for the last seven days. The individual day score is adjusted for each day old that the score is recorded. We call this decay: the computation is done in SQL but if it were done in Java it would look something like this:
    Calendar c = Calendar.getInstance();
       c.add(Calendar.DATE, -daysAgo);
       Date now = new Date();
       Date nDaysAgo = c.getTime();
       long dateDiff = now.getTime() - nDaysAgo.getTime();
       long dateAdjustment = dateDiff / 86400000;
       long decayedScore = score / (1 + dateAdjustment);
  • Add the results of the second and third steps together.

For example, a user published a blog post 2 months ago and through some sort of magic, it got 3 comments every day for the last 2 months (and it's already received 2 comments today that haven't been archived to the jivePopularity table). We only take into account the popularity score for the last seven days so the total score is going to be the sum of the following scores:

Date Number of comments Recorded score Score with decay
6/5/2008 (today) 3 15 15
6/4/2008 3 15 7
6/3/2008 3 15 5
6/2/2008 3 15 3
6/1/2008 3 15 3
5/31/2008 3 15 2
5/30/2008 3 15 2
Total Score     37

Finally, each item is added to a SortedSet, and then copied back to ActivityManagerImpl, where it lives until the next time popularity is calculated fifteen minutes later.

So when you see a widget that shows the most popular items for a given space, project, social group or blog, you're getting the n items who have the highest combined score, which is a combination of comments, replies, edits and views, decayed over the last seven days.

How do I hide the border of a widget?

The short way is like this:

.jive-widget {border:none !important;}

If you wanted to remove the background on the header:

.jive-widget .jive-widget-header {background:transparent !important;}

But  you might want an underline so that people know it is the header:

.jive-widget .jive-widget-header {
     background:transparent !important;
     border-bottom:1px dashed gray;
 }

Note that not all the widgets are controlled by these two pieces of CSS. So further work would be needed in the profile, actions, and other elements.