Widgets: Frequently Asked Questions

Version 6

    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 homepages (overview tab) and gives end users the ability to personalize their view into the system. 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, which 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 using either RSS or JSON. There's an excellent discussion with examples in this thread:  http://www.jivesoftware.com/community/message/52320

    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'll want to append an identifier to the DOM element ID's that you create/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) />
    

    and 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 will call 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 absolutely 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 better yet that extends BaseWidget).  That's the bare minimum and assumes no design-time properties. If you want design-time props, then you'll 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. So for example, let's say I 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?

    Short & Sweet.

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

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

     

    And last -- a disclaimer that not all the widgets are controlled by these 2 pieces of CSS. So further work would be needed in the profile, actions, etc.1