Dojo in XPages – 21: Displaying Images with a ThumbnailPicker

If you have images attached to a document in an XPages application, you can display a scrolling series of them with the ThumbnailPicker widget. In this post, I’ll show how to include the required dojo modules and dynamically populate the picker with a list of images.

Dojo in XPages Series

Dojo in XPages — All Blog Posts

ThumbnailPicker Widget

The ThumbnailPicker widget can display images horizontally or vertically and it provides controls to page through the images. If you have a document with multiple image attachments, it can be a handy way to display thumbnails of them.

Here’s an example of each orientation from my test page.


Including Required Dojo Resources

The ThumbnailPicker widget is part of dojox; it’s already on the Domino server and can be used on the page by adding a few resources and a div to render it.

There are two dojo modules and one dojo stylesheet required in order to make this work.

You need the ThumbnailPicker module, the ItemFileReadStore module (to supply the list of images to the widget), and a stylesheet to display it properly.

  <xp:dojoModule name="dojox.image.ThumbnailPicker"></xp:dojoModule>
  <xp:dojoModule name=""></xp:dojoModule>
  <xp:styleSheet href="/.ibmxspres/dojoroot/dojox/image/resources/image.css"></xp:styleSheet>

Providing Data

The ThumbnailPicker requires an ItemFileReadStore to provide the image information.

The structure generally looks like this: = {
  identifier: 'title',
  label: 'Images',
  items: [
      thumb: "",
      title: "title 1"
      thumb: "",
      title: "title 2"

In order to build this based on attachments on the current document, we want to build that list of items dynamically.

Each image url needs to be built in this format: DB.nsf/0/[docUNID]/$File/[attachmentname]

The code below will build that structure based on the files attached to the current document. It can run in the page’s onClientLoad event.

Line 2 gets the list of attachment names with @AttachmentNames().

Line 4 parses it to be an array, because it is returned to client-side javascript as a string surrounded in square brackets, with each value separated by a comma and a space. [file1.jpg, file2.jpg, file3.jpg]

Lines 7 and 8 set up objects that are required by the data store for the ThumbnailPicker. The itemNameMap object defines the property that points to the image “thumbnail” (in quotes because we’re not really using a thumbnail — we’ll just display the actual attachment as a thumbnail). The request object doesn’t need any parameters in this case. That’s used when making remote requests.

As shown previously, the data store needs an items property that is an array of objects (each with a thumb property and a title property). Lines 11 – 19 build array of objects for the data store.

Lines 22-26 set up the actual ItemFileReadStore object and provide it the data. The identifer property tells it which data property to use for the image title (which you see when you hover your mouse over the image).

Line 29 finds the div with the id thumbnailDisplay and connects the data store to it in order to initialize it.

// Get an array of attachment names.
var fileNames =	"#{javascript:@AttachmentNames();}";
// It comes back as a concatenated string, surrounded by square brackets, to parse into an array
fileNames = fileNames.substring(1, fileNames.length-1).split(', ');

var docID = "#{javascript:currentDocument.getDocument().getUniversalID()}";
var itemNameMap = {imageThumbAttr: "thumb"};
var request= {};

// Build an array of image items for the thumbnail's data store
var imageData = {};
imageData.items = [];
for (var i=0; i< fileNames.length; i++) {
  var newItem = {};
  newItem.thumb = './0/' + docID + '/$File/' + fileNames[i];
  newItem.title = 'Image: ' + fileNames[i];

// Initialize the data store
var imageStore = new{
  identifier: 'title',
  label: 'Images',
  data: imageData

// Initialize the Thumbnail Picker 
dijit.byId('thumbnailDisplay').setDataStore(imageStore, request, itemNameMap);

Rendering the ThumbnailPicker

Here’s how you can set up a passthru HTML div tag to become the ThumbnailPicker.

<div id="thumbnailDisplay" dojoType="dojox.image.ThumbnailPicker"
  size="500" data-dojo-props="isHorizontal:true">

The key is the dojoType attribute. When the dojo parser runs, it looks for these dojoType attributes and generates dijits. So, if you use this method, you’ll need to enable the page’s Trigger Dojo parse on load property to ensure that the parser runs when the page loads. (Otherwise, it won’t generate the dijit.)


As you can see in the page source above, this adds the attribute dojoParseOnLoad="true" to the xp:view tag.

Now, you’ve got what you need to generate the ThumbnailPicker.

Another option for Rendering the ThumbnailPicker

In addition to passthru HTML, we can also render the ThumbnailPicker with an xp:div tag.

You can achieve the same output by setting the dojo type to dojox.image.ThumbnailPicker and adding attributes for the size, etc. (Click on the picture to enlarge it.)


After you do that, you would just need to change the last line of the onClientLoad code to retrieve the XPages-generated client-side ID for the div.

dijit.byId('#{id:thumbnailDisplay}').setDataStore(imageStore, request, itemNameMap);

ThumbnailPicker Size

The size attribute generally defines the width (or height, if vertical) of the picker.

There’s also a numberThumbs attribute that’s supposed to define the number of images to display, but I did not have much success in getting it to take effect.

Resizing the Images

By default, this will dispay the images in their original sizes. Fortunately, with some CSS, you can resize them to make them consistent.

For my example, I created another stylesheet and included it as a page resource, based on an example found in the Dojo documentation.

.thumbWrapper img {
  height: 100px;
  max-width: 75px;
.thumbOuter.thumbHoriz, .thumbHoriz .thumbScroller {
  height: 100px;

Displaying the ThumbnailPicker Vertically

In the div tag shown above, there’s a data-dojo-props attribute with a value of "isHorizontal:true". That property isn’t required, as that’s the default, but it shows how you can easily change the orientation of the display. If you set that property to false, it will display the picker vertically.


4 responses to “Dojo in XPages – 21: Displaying Images with a ThumbnailPicker”

  1. Gary Capra says :

    Hi Brad, This picker is just what I’ve been looking for to display uploaded images. However I can’t seem to get it to function, every time I try to add the code (I’m using your code as it is on this page) to load the attached images I get an error (in the Problems view):
    Binding syntax error in property ‘action’: Lexical error at line 29, column 86. Encountered: after : “\’s data store\nvar imageData = {};\nimageData.items = [];\nfor (var i=0; i< fileNames.length; i++) {\n var newItem = {};\n newItem.thumb = \"./0/\" + docID + \"/$File/\" + fileNames[i];\n newItem.title = \"Image: \" + fileNames[i];\n \n imageData.items.push(newItem);\n}\n \n// Initialize the data store\nvar imageStore = new{\n identifier: \"title\",\n label: \"Images\",\n data: imageData\n});\n \n// Initialize the Thumbnail Picker \ndijit.byId(\"#{id:thumbnailDisplay}\").setDataStore(imageStore, request, itemNameMap);}" ccIncidentFileAttachments.xsp SafetyIncident(1).nsf/CustomControls line 271 XPages Problem

    Any ideas on what I might be doing wrong.


  2. Brad Balassaitis says :

    I don’t see anything in the API for the ThumbnailPicker to display a label, but the Gallery gives you that ability:

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: